python之反射和內置函數__str__、__repr__

複製代碼
1、反射
反射類中的變量
反射對象中的變量
反射模塊中的變量
反射本文件中的變量

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__)



2、內置方法__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__,沒有就去父類找,
#父類有就執行,沒有就打印對象空間地址
複製代碼
相關文章
相關標籤/搜索