python之反射和内置函数__str____repr__

Posted 从入门到出门

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python之反射和内置函数__str____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__的主要内容,如果未能解决你的问题,请参考以下文章

python26 封装 多态 常用的内置函数 `__str__` `__del__` 反射 动态导入模块

python3全栈开发-内置函数补充,反射,元类,__str__,__del__,exec,type,__call__方法

17 Apr 18 内置函数(isinstance,issubclass)反射 __str__ __del__ __call__ 元类

Python基础之反射

8.python之面相对象part.6(反射&__call__,__setattr__,__delattr__,__getattr__)

issubclass和isinstance,反射,内置方法