《Python》反射、內置方法(__str__,__repr__)


一、反射

   通過字符串的形式操作對象相關的屬性。(使用字符串數據類型的變量名來獲取這個變量的值)

    Python中的一切事物都是對象(都可以使用反射)

      反射類中的變量

      反射對象中的變量

      反射模板中的變量

      反射本文件中的變量

    用反射的場景:

      input

      網絡

      文件

#hasattr

def hasattr(*args, **kwargs): # real signature unknown
    """
    Return whether the object has an attribute with the given name.
    
    This is done by calling getattr(obj, name) and catching AttributeError.
    """
    pass



#getattr

def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """
    pass



#setattr

def setattr(x, y, v): # real signature unknown; restored from __doc__
    """
    Sets the named attribute on the given object to the specified value.
    
    setattr(x, 'y', v) is equivalent to ``x.y = v''
    """
    pass



#delattr

def delattr(x, y): # real signature unknown; restored from __doc__
    """
    Deletes the named attribute from the given object.
    
    delattr(x, 'y') is equivalent to ``del x.y''
    """
    pass
反射的4種方法源碼

   

  1、getattr()

    getattr(變量名:命名空間,字符串:屬於一個命名空間內的變量名)

      類名.靜態屬性  getattr(類名,‘靜態屬性’)

      類名.類方法()   getattr(類名,‘類方法’)()

      類名.靜態方法()  getattr(類名,‘靜態方法’)()

      

      對象.對象屬性  getattr(對象,‘對象屬性’)

      對象.方法()    getattr(對象,‘方法’)()

 

      模塊名.方法名

      模塊名.類名

      模塊名.變量

      模塊名.函數

 

      本文件反射  import sys

      getattr(sys.modules[__name__],'所有定義在這個文件中的名字')

# 反射類中的變量: 靜態屬性、類方法、靜態方法
class Foo:
    school = 'oldboy'
    country = 'china'
    language = 'chiness'

    @classmethod     # 類方法
    def class_method(cls):
        print(cls.school)

    @staticmethod    # 靜態方法
    def static_method():
        print('in staticmethod')

    def wahaha(self):  # 普通方法
        print('wahaha')

print(Foo.school)   # oldboy
print(Foo.country)  # china
print(Foo.language) # chiness

# 判斷實現
inp = input('>>>')
if inp == 'school': print(Foo.school)       # oldboy
elif inp == 'country': print(Foo.country)   # china
elif inp == 'language': print(Foo.language) # chiness

# 反射實現
while 1:
    inp = input('>>>')      # 輸school,打印oldboy    輸country,打印china    輸language,打印chiness
    print(getattr(Foo,inp))

# 解析getattr方法
print(getattr(Foo,'school'))   # oldboy
Foo.class_method()              # oldboy
print(getattr(Foo,'class_method'))  # <bound method Foo.class_method of <class '__main__.Foo'>>
getattr(Foo,'class_method')()  # oldboy     相當於:Foo.class_method()
getattr(Foo,'static_method')() # in staticmethod    相當與:Foo.static_method()

 

 

    

# 反射對象中的變量

class Foo:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def eating(self):
        print('%s is eating' % self.name)
alex = Foo('alex',38)
print(getattr(alex,'name'))   # alex  反射對象屬性
print(getattr(alex,'age'))    # 38  
getattr(alex,'eating')()     # alex is eating  反射對象方法

 

 

# 反射模塊中的變量
import os   # os就是一個模塊
os.rename('D:\\python_task1.py','D:\\python_task2.py')
getattr(os,'rename')    # 把python_task1.py改成了python_task2.py
getattr(os,'D:\\python_task1.py','D:\\python_task2.py') # 效果同上

 

 

# 反射本文件中的變量

a = 1
b = 2
name = 'alex'

def qqxing():
    print('like eat qqxing')

class Foo:
    pass

import sys

print(sys.modules['__main__'])  # 本文件的命名空間
print(sys.modules['__main__'].a)    # 1
print([__name__])   # ['__main__']

print(sys.modules[__name__])    #  反射本文件中的變量 固定的使用這個命名空間
print(getattr(sys.modules[__name__],'a'))   # 1
print(getattr(sys.modules[__name__],'b'))   # 2
print(getattr(sys.modules[__name__],'name'))   # alex
getattr(sys.modules[__name__],'qqxing')()   # like eat qqxing
print(getattr(sys.modules[__name__],'Foo')) # <class '__main__.Foo'>     Foo類的地址
print(getattr(sys.modules[__name__],'Foo')())    # <__main__.Foo object at 0x0072BED0>    Foo類對象的地址

 

 

  2、hasattr()

    hasattr(變量名:命名空間,字符串:屬於一個命名空間內的變量名)  成立返回Ture,不成立返回False,一般與getattr搭配使用

class Foo:
    school = 'oldboy'
    country = 'china'
    language = 'chiness'

    @classmethod
    def class_method(cls):
        print(cls.school)

    @staticmethod
    def static_method():
        print('in staticmethod')

    def wahaha(self):
        print('wahaha')

inp = input('>>>')  # 輸入 haha
print(getattr(Foo, inp))
# 如果輸入的不存在則報錯
# AttributeError: type object 'Foo' has no attribute 'haha'
# 所以要給他定義一個判斷條件

inp = input('>>>')
if hasattr(Foo,inp):    # 如果輸入的字符串在這個類中,則成立
    print(getattr(Foo,inp))

 

 

  3、setattr()

    setattr(名稱空間,變量名,變量值)  更改變量的值

      給命名空間的某一個名字設置一個值

# setattr:接受三個參數 命名空間 ‘變量名’ 變量值
class Foo:
    school = 'oldboy'

def func():
    print('wahaha')

Foo.school = 'OLDBOY'   # 直接更改
print(Foo.school)       # OLDBOY
setattr(Foo,'school','OLDOBY')  # 有school這個屬性則更改
print(Foo.school)       # OLDBOY
print(getattr(Foo,'school'))
setattr(Foo,'name','alex')  # 沒有name這個屬性則添加
print(Foo.name)         # alex
print(Foo.__dict__)

setattr(Foo,'func',func)    # 往類中添加方法,不過一般沒人這么做
Foo.func()                  #wahaha
func()                      #wahaha
print(Foo.__dict__)  
'''
{'__module__': '__main__', 'Country': 'China', '__dict__': <attribute '__dict__' of 'Foo' objects>, 
'__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': None, 'func': <function func at 0x00788D68>}
'''

 

 

  4、delattr()

    delattr(命名空間,變量)

      刪除某一個命名空間中變量對應的值

class Foo:
    school = 'oldboy'
    country = 'china'
    language = 'chiness'

    def wahaha(self):
        print('wahaha')

    def qqxing(self):
        print('qqxing')

del Foo.country         # 直接刪除一個屬性
print(Foo.__dict__)
delattr(Foo,'school')   # 使用delattr刪除一個屬性
print(Foo.__dict__)
del Foo.wahaha          # 直接刪除一個方法
print(Foo.__dict__)
delattr(Foo,'qqxing')   # 使用delattr刪除一個方法
print(Foo.__dict__)

 

 

二、內置方法

    在不是需要程序員定義,本身就存在在類中的方法就是內置方法

    內置的方法通常都長這樣:__名字__

    各種不同叫法:名字+(雙下方法、魔術方法、內置方法)

    所有的雙下方法,都不需要我們直接去調用,都有另外一種自動觸發它的語法

 

   __init__:

    不需要我們主動調用,而是在實例化的時候內部自動調用的

 

   __str__ 和 __repr__:  

    這倆方法的返回值必須是字符串,否則拋出異常。  

   __str__:
    當你打印一個對象的時候 觸發__str__
    當你使用%s格式化的時候 觸發__str__
    str強轉數據類型的時候 觸發__str__

   __repr__:
    repr是str的備胎
    有__str__的時候執行__str__,沒有實現__str__的時候,執行__repr__
    repr(obj)內置函數對應的結果是 __repr__的返回值
    當你使用%r格式化的時候 觸發__repr__
class Course:

    def __init__(self,name,period,price,teacher):
        self.name = name
        self.period = period
        self.price = price
        self.teacher = teacher

    def __repr__(self):
        return 'repr : %s %s %s %s ' % (self.name,self.period,self.price,self.teacher)

    def __str__(self):
        return 'str : %s %s %s %s ' % (self.name, self.period, self.price, self.teacher)

course_lst = []
python = Course('python','6 month',29800,'alex')
course_lst.append(python)
linux = Course('linux','5 month',19800,'oldboy')
course_lst.append(linux)
for id,course in enumerate(course_lst,1):
    print(id,course)   # 1 str : python 6 month 29800 alex
                        # 2 str : linux 5 month 19800 oldboy

    print('%s %s' % (id,course))   # 效果同上

    print(str(course))      # str : python 6 month 29800 alex
                            # str : linux 5 month 19800 oldboy

    print(repr(course))     # repr : python 6 month 29800 alex
                            # repr : linux 5 month 19800 oldboy

    print('%r' % course)    # 效果同上

# __str__
# 當你打印一個對象的時候 觸發__str__
# 當你使用%s格式化的時候 觸發__str__
# str強轉數據類型的時候  觸發__str__

# __repr__
# repr是str的備胎
# 有__str__的時候執行__str__,沒有實現__str__的時候,執行__repr__
# repr(obj)內置函數對應的結果是 __repr__的返回值
# 當你使用%r格式化的時候 觸發__repr__

 

    

#子類與父類的__str__和__repr__觸發順序:

class Foo:
    def __str__(self):
        return 'Foo.str'
    def __repr__(self):
        return 'Foo.repr'

class Son(Foo):
    def __str__(self):
        return 'Son.str'
    def __repr__(self):
        return 'Son.str'

obj = Son()
print(obj)
'''
當打印子類的對象時:
1、先從子類找__str__
2、子類中沒有__str__,則到父類找__str__
3、子類和父類都沒有__str__,則找子類的__repr__
4、子類和父類都沒有__str__,且子類沒有__repr__,則找父類的__repr__
'''

 

 

    

 

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM