python之反射和内置函数__str__、__repr__

python

一、反射

反射类中的变量

反射对象中的变量

反射模块中的变量

反射本文件中的变量

1、定义:使用字符串数据类型的变量名 来获取这个变量的值

例如:

name = 'xiaoming'

print(name) # xiaoming

print('name') # name

平时我们要想获取'xiaoming'这个值,要用name去获取,但是如果想用字符串'name' 获取这个值呢,

就需要用到反射。

2、反射应用的场景(就是把接收的字符串转换成变量的名字便于使用)

1,input

用户输入的如果是a,那么就打印1,如果输入的是b就打印2,如果输入的是name,就打印xiaoming

2,文件

从文件中读出的字符串,想转换成变量的名字

3,网络

将网络传输的字符串转换成变量的名字

3、反射类中的变量 : 静态属性,类方法,静态方法

class Foo:

School = 'Zhbit'

Country = 'China'

language = 'Chiness'

@classmethod

def class_method(cls):

print('in class_method')

@staticmethod

def static_method():

print('in staticmethod')

def hahaha(self):

print('hahaha')

# 如果要实现输入School就打印对应的值,Country也打印对应的值,那么:

# 1,用判断实现:

inp = input('请输入:')

if inp == 'School':print(Foo.School)

elif inp == 'Country':print(Foo.Country)

elif inp == 'language':print(Foo.language)

# 在属性少的时候这样写,没什么问题,但是想一想,如果有100个属性呢,你要写100次判断吗?

所以,请看反射。

# 2,反射实现

while True:

inp = input('>>>')

print(getattr(Foo,inp))

# OK,这就实现了,而且无论多少个属性,都可以实现,很简单吧!

# 那么下面就来解析反射需要用到的方法

2-1getattr方法

用法:getattr(变量名(命名空间),字符串(属于一个命名空间内的变量名))

# 获取静态属性

print(getattr(Foo,'School')) # 就等于 Foo.School

print(getattr(Foo,'class_method')) # 就等于 Foo.class_method 得到的是一个函数地址

print(getattr(Foo,'static_method')) #就等于 Foo.static_method 得到的是一个函数地址

# 若想执行这个函数

getattr(Foo,'class_method')() # in class_method

getattr(Foo,'static_method')() # in staticmethod

2-2hasattr方法

# 要是没有这个属性或者方法就会报错,那么出于安全考虑,就需要判断有没有这个属性或者方法才去执行

# 就要用到hasattr()

print(hasattr(Foo,'class_method')) #True

print(hasattr(Foo,'hello')) # False

while True:

inp = input('请输入:')

if hasattr(Foo,inp):

print(getattr(Foo,inp))

4、反射对象属性,普通方法

class Foo:

def __init__(self,name,age):

self.name = name

self.age = age

def sleep(self):

print('%s在睡觉,快打死他' %self.name)

xiaobai = Foo('小白',12)

print(getattr(xiaobai,'name'))

getattr(xiaobai,'sleep')()

5、反射模块中的变量

import os # os就是一个模块

os.rename('a.txt','a.bak')

getattr(os,'rename')('a.bak','a.txt')

6、反射本文件中的变量

a = 1

b = 2

age = 18

# 函数

def func():

print(666)

# 类

class A:pass

import sys

print(sys.modules['__main__']) # 本文件的命名空间

print(sys.modules['__main__'].a) # 本文件的命名空间中的a变量的值:1

print(sys.modules['__main__'].func) # 本文件的命名空间中函数func的地址:<function func at 0x000001C735B81E18>

print(sys.modules['__main__'].A) # 本文件的命名空间中类A的地址:<class '__main__.A'>

# __name__ 与 '__main__' 一样,代表本文件的命名空间

print(sys.modules['__main__'])

print(sys.modules[__name__])

# 反射

print(getattr(sys.modules[__name__],'a')) # 1

print(getattr(sys.modules['__main__'],'a')) # 1

print(getattr(sys.modules[__name__],'age')) # 18

getattr(sys.modules[__name__],'func')() #执行函数func:666

obj = getattr(sys.modules[__name__],'A')() #实例化对象

print(obj)

7、setattr:增和改

# 类

class Foo:

country = 'China'

# 函数

def func():

print(666)

print(getattr(Foo,'country')) # China

setattr(Foo,'country','Big China') # 接受三个参数:命名空间 '变量名' 变量值

print(getattr(Foo,'country')) # Big China

setattr(Foo,'fun',func) # 为类Foo新增一个属性fun,值为func函数的地址

print(func) # <function func at 0x00000188B34F2D08>

print(Foo.fun) # <function func at 0x0000026DC4A21E18>

getattr(Foo,'fun')() # 666

8、delattr:删

class Foo:

language = '火星文'

country = 'China'

def func():

print(666)

print(Foo.__dict__)

delattr(Foo,'language')

print(Foo.__dict__)

二、内置方法__str__和__repr__

1、内置方法的定义

不需要程序员定义,本身就存在类中的方法就是内置方法,

它不用我们直接调用,当遇到特定的场景就会自动触发,

内置的方法通常都长这样 : __名字__

可以叫 : 双下方法、 魔术方法、 内置方法

比如我们熟悉的初始化函数__init__()就是内置方法,

实例化对象的时候就自动执行

2、__str__和__repr__

__str__

当你打印一个对象的时候print(obj) 触发__str__

当你使用%s格式化的输出对象时候print('%s' %obj) 触发__str__

str强转数据类型的时候str(obj) 触发__str__

__repr__

repr是str的备胎

直接打印对象,有__str__的时候执行__str__,没有__str__的时候,执行__repr__

当你使用%r输出对象时候print('%r' %obj) 触发__repr__

repr强转数据类型的时候repr(obj) 触发__repr__

注意:__str__ 和__perp__都必须要用return,而且返回值必须是字符串

例子:

class Fruit:

def __init__(self,name,price):

self.name = name

self.price = price

def __str__(self):

return 'in str:%s的价格是:%s' %(self.name,self.price)

def __repr__(self):

return 'in repr:%s的价格是:%s' % (self.name, self.price)

apple = Fruit('苹果',5)

# 直接打印对象,有__str__的时候执行__str__,没有__str__的时候,执行__repr__

print(apple) # in str:苹果的价格是:5

# 当你使用%s格式化的输出对象时候print('%s' %obj) 触发__str__

print('%s' %apple) # in str:苹果的价格是:5

# 当你使用%r输出对象时候print('%r' %obj) 触发__repr__

print('%r' %apple) # in repr:苹果的价格是:5

# str强转数据类型的时候str(obj) 触发__str__

print(str(apple)) # in str:苹果的价格是:5

# repr强转数据类型的时候repr(obj) 触发__repr__

print(repr(apple)) # in repr:苹果的价格是:5

升级:

class Fruit:

def __str__(self):

return 'Fruit_str'

def __repr__(self):

return 'Fruit_repr'

class Apple(Fruit):

def __str__(self):

return 'Apple_str'

def __repr__(self):

return 'Apple_repr'

apple = Apple()

print(apple)

# apple是Apple类对象,直接打印,先从Apple类找,有__str__的时候执行Apple的__str__,没有__str__的时候,

# 从父类去找__str__,父类有就执行,如果父类没有,就找子类的__repr__,有就执行子类的__repr__,没有就去父类找,

#父类有就执行,没有就打印对象空间地址

一、反射

反射类中的变量

反射对象中的变量

反射模块中的变量

反射本文件中的变量

1、定义:使用字符串数据类型的变量名 来获取这个变量的值

例如:

name = 'xiaoming'

print(name) # xiaoming

print('name') # name

平时我们要想获取'xiaoming'这个值,要用name去获取,但是如果想用字符串'name' 获取这个值呢,

就需要用到反射。

2、反射应用的场景(就是把接收的字符串转换成变量的名字便于使用)

1,input

用户输入的如果是a,那么就打印1,如果输入的是b就打印2,如果输入的是name,就打印xiaoming

2,文件

从文件中读出的字符串,想转换成变量的名字

3,网络

将网络传输的字符串转换成变量的名字

3、反射类中的变量 : 静态属性,类方法,静态方法

class Foo:

School = 'Zhbit'

Country = 'China'

language = 'Chiness'

@classmethod

def class_method(cls):

print('in class_method')

@staticmethod

def static_method():

print('in staticmethod')

def hahaha(self):

print('hahaha')

# 如果要实现输入School就打印对应的值,Country也打印对应的值,那么:

# 1,用判断实现:

inp = input('请输入:')

if inp == 'School':print(Foo.School)

elif inp == 'Country':print(Foo.Country)

elif inp == 'language':print(Foo.language)

# 在属性少的时候这样写,没什么问题,但是想一想,如果有100个属性呢,你要写100次判断吗?

所以,请看反射。

# 2,反射实现

while True:

inp = input('>>>')

print(getattr(Foo,inp))

# OK,这就实现了,而且无论多少个属性,都可以实现,很简单吧!

# 那么下面就来解析反射需要用到的方法

2-1getattr方法

用法:getattr(变量名(命名空间),字符串(属于一个命名空间内的变量名))

# 获取静态属性

print(getattr(Foo,'School')) # 就等于 Foo.School

print(getattr(Foo,'class_method')) # 就等于 Foo.class_method 得到的是一个函数地址

print(getattr(Foo,'static_method')) #就等于 Foo.static_method 得到的是一个函数地址

# 若想执行这个函数

getattr(Foo,'class_method')() # in class_method

getattr(Foo,'static_method')() # in staticmethod

2-2hasattr方法

# 要是没有这个属性或者方法就会报错,那么出于安全考虑,就需要判断有没有这个属性或者方法才去执行

# 就要用到hasattr()

print(hasattr(Foo,'class_method')) #True

print(hasattr(Foo,'hello')) # False

while True:

inp = input('请输入:')

if hasattr(Foo,inp):

print(getattr(Foo,inp))

4、反射对象属性,普通方法

class Foo:

def __init__(self,name,age):

self.name = name

self.age = age

def sleep(self):

print('%s在睡觉,快打死他' %self.name)

xiaobai = Foo('小白',12)

print(getattr(xiaobai,'name'))

getattr(xiaobai,'sleep')()

5、反射模块中的变量

import os # os就是一个模块

os.rename('a.txt','a.bak')

getattr(os,'rename')('a.bak','a.txt')

6、反射本文件中的变量

a = 1

b = 2

age = 18

# 函数

def func():

print(666)

# 类

class A:pass

import sys

print(sys.modules['__main__']) # 本文件的命名空间

print(sys.modules['__main__'].a) # 本文件的命名空间中的a变量的值:1

print(sys.modules['__main__'].func) # 本文件的命名空间中函数func的地址:<function func at 0x000001C735B81E18>

print(sys.modules['__main__'].A) # 本文件的命名空间中类A的地址:<class '__main__.A'>

# __name__ 与 '__main__' 一样,代表本文件的命名空间

print(sys.modules['__main__'])

print(sys.modules[__name__])

# 反射

print(getattr(sys.modules[__name__],'a')) # 1

print(getattr(sys.modules['__main__'],'a')) # 1

print(getattr(sys.modules[__name__],'age')) # 18

getattr(sys.modules[__name__],'func')() #执行函数func:666

obj = getattr(sys.modules[__name__],'A')() #实例化对象

print(obj)

7、setattr:增和改

# 类

class Foo:

country = 'China'

# 函数

def func():

print(666)

print(getattr(Foo,'country')) # China

setattr(Foo,'country','Big China') # 接受三个参数:命名空间 '变量名' 变量值

print(getattr(Foo,'country')) # Big China

setattr(Foo,'fun',func) # 为类Foo新增一个属性fun,值为func函数的地址

print(func) # <function func at 0x00000188B34F2D08>

print(Foo.fun) # <function func at 0x0000026DC4A21E18>

getattr(Foo,'fun')() # 666

8、delattr:删

class Foo:

language = '火星文'

country = 'China'

def func():

print(666)

print(Foo.__dict__)

delattr(Foo,'language')

print(Foo.__dict__)

二、内置方法__str__和__repr__

1、内置方法的定义

不需要程序员定义,本身就存在类中的方法就是内置方法,

它不用我们直接调用,当遇到特定的场景就会自动触发,

内置的方法通常都长这样 : __名字__

可以叫 : 双下方法、 魔术方法、 内置方法

比如我们熟悉的初始化函数__init__()就是内置方法,

实例化对象的时候就自动执行

2、__str__和__repr__

__str__

当你打印一个对象的时候print(obj) 触发__str__

当你使用%s格式化的输出对象时候print('%s' %obj) 触发__str__

str强转数据类型的时候str(obj) 触发__str__

__repr__

repr是str的备胎

直接打印对象,有__str__的时候执行__str__,没有__str__的时候,执行__repr__

当你使用%r输出对象时候print('%r' %obj) 触发__repr__

repr强转数据类型的时候repr(obj) 触发__repr__

注意:__str__ 和__perp__都必须要用return,而且返回值必须是字符串

例子:

class Fruit:

def __init__(self,name,price):

self.name = name

self.price = price

def __str__(self):

return 'in str:%s的价格是:%s' %(self.name,self.price)

def __repr__(self):

return 'in repr:%s的价格是:%s' % (self.name, self.price)

apple = Fruit('苹果',5)

# 直接打印对象,有__str__的时候执行__str__,没有__str__的时候,执行__repr__

print(apple) # in str:苹果的价格是:5

# 当你使用%s格式化的输出对象时候print('%s' %obj) 触发__str__

print('%s' %apple) # in str:苹果的价格是:5

# 当你使用%r输出对象时候print('%r' %obj) 触发__repr__

print('%r' %apple) # in repr:苹果的价格是:5

# str强转数据类型的时候str(obj) 触发__str__

print(str(apple)) # in str:苹果的价格是:5

# repr强转数据类型的时候repr(obj) 触发__repr__

print(repr(apple)) # in repr:苹果的价格是:5

升级:

class Fruit:

def __str__(self):

return 'Fruit_str'

def __repr__(self):

return 'Fruit_repr'

class Apple(Fruit):

def __str__(self):

return 'Apple_str'

def __repr__(self):

return 'Apple_repr'

apple = Apple()

print(apple)

# apple是Apple类对象,直接打印,先从Apple类找,有__str__的时候执行Apple的__str__,没有__str__的时候,

# 从父类去找__str__,父类有就执行,如果父类没有,就找子类的__repr__,有就执行子类的__repr__,没有就去父类找,

#父类有就执行,没有就打印对象空间地址

以上是 python之反射和内置函数__str__、__repr__ 的全部内容, 来源链接: utcz.com/z/388253.html

回到顶部