Python反射和內置方法(雙下方法)

Python反射和內置方法(雙下方法)

1、反射

  1. 什麼是反射php

    反射的概念是由Smith在1982年首次提出的,主要是指程序能夠訪問、檢測和修改它自己狀態或行爲的一種能力(自省)。這一律唸的提出很快引起了計算機科學領域關於應用反射性的研究。它首先被程序語言的設計領域所採用,並在Lisp和麪向對象方面取得了成績。java

  2. Python面向對象中的反射python

    經過字符串的形式操做對象相關的屬性。Python中的一切事物都是對象(均可以使用反射)程序員

    四個能夠實現自省的函數:app

    1. hasattr():檢測是否含有某屬性函數

      class Foo:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def func(self):
              pass
      
      # 檢測是否含有某屬性
      print(hasattr(Foo, "func"))       # True
      f = Foo("dogfa", 18)
      print(hasattr(f, "name"))     # True
      print(hasattr(f, "gender"))       # False
    2. getattr():獲取屬性設計

      class Foo:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def func(self):
              pass
      
          @staticmethod
          def staticfunc():
              print("嘿嘿嘿")
      
      # 獲取屬性
      f = getattr(Foo, "staticfunc")
      print(f)  # <function Foo.staticfunc at 0x0000028DD8EB9D08>
      f()           # 嘿嘿嘿
      
      # 若是要獲取的屬性不存在那麼就會報錯
      f2 = getattr(Foo, "func1")    # AttributeError: type object 'Foo' has no attribute 'func1'
    3. setattr():設置屬性code

      class Foo:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def func(self):
              pass
      
          @staticmethod
          def staticfunc():
              print("嘿嘿嘿")
      
      
      f = Foo("dogfa", 18)
      print(f.__dict__)     # {'name': 'dogfa', 'age': 18}
      setattr(f, "name", f.name + "sb")
      print(f.__dict__)     # {'name': 'dogfa_sb', 'age': 18}
    4. defattr():刪除屬性orm

      class Foo:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def func(self):
              pass
      
          @staticmethod
          def staticfunc():
              print("嘿嘿嘿")
      
      f = Foo("dogfa", 18)
      print(f.__dict__)     # {'name': 'dogfa', 'age': 18}
      delattr(f, "name")
      print(f.__dict__)     # {'age': 18}
      
      # delattr(f, "gender")    # 刪除不存在的屬性時會報錯
  3. 使用反射的場景對象

    1. 對對象的反射
    2. 對類的反射
    3. 其它模塊的反射
    4. 當前模塊的反射

2、內置方法

  1. 函數與方法的區別

    在說方法以前咱們先來講一下在Python中函數和方法的區別。

    # 經過導入types模塊來驗證
    from types import FunctionType, MethodType
    
    def func():
        pass
    
    class A:
        def func(self):
            pass
    
        @staticmethod
        def func2():
            pass
    
    obj = A()
    
    # FunctionType:函數    MethodType:方法
    print(isinstance(func, FunctionType))        # True
    print(isinstance(A.func, FunctionType))      # True
    print(isinstance(obj.func, FunctionType))    # False
    print(isinstance(obj.func, MethodType))      # True
    print(isinstance(A.func2, FunctionType)) # True
    print(isinstance(obj.func2, FunctionType))   # True
    
    
    
    # 經過打印函數(方法)名驗證
    from types import FunctionType, MethodType
    def func():
        pass
    
    class A:
        def func(self):
            pass
    
        @staticmethod
        def func2():
            pass
    
    obj = A()
    
    print(func)      # <function func at 0x000002013BC32E18>
    print(A.func)    # <function A.func at 0x000002013BF6A598>
    print(obj.func)  # <bound method A.func of <__main__.A object at 0x000002013BDF7DD8>>

    總結:

    (1)函數的是顯式傳遞數據的。如咱們要指明爲len()函數傳遞一些要處理數據。

    (2)函數則跟對象無關。

    (3)方法中的數據則是隱式傳遞的。

    (4)方法能夠操做類內部的數據。

    (5)方法跟對象是關聯的。如咱們在用strip()方法時,都是要經過str對象調用,好比咱們有字符串s,而後s.strip()這樣調用。是的,strip()方法屬於str對象。

    (6)靜態方法就是函數

  2. 內置方法(雙下方法)

    定義:雙下方法是特殊方法,他是解釋器提供的 由爽下劃線加方法名加雙下劃線 __方法名__的具備特殊意義的方法,雙下方法主要是Python源碼程序員使用的,咱們在開發中儘可能不要使用雙下方法,可是深刻研究雙下方法,更有益於咱們閱讀源碼。

    調用:不一樣的雙下方法有不一樣的觸發方式,就比如盜墓時觸發的機關同樣,不知不覺就觸發了雙下方法,例如:__init__

    1. item系列

      class Foo:
          def __init__(self, name, age):
              self.name = name
              self.age = age
      
          def __getitem__(self, item):
              print("執行obj['key']時會執行我")
              return getattr(self, item)
      
          def __setitem__(self, key, value):
              print("執行obj['key'] = value 時會執行我")
              setattr(self, key, value)
      
          def __delitem__(self, key):
              print("執行del['key']時會執行我")
              delattr(self,  key)
      
      obj = Foo("oldwang", 20)
      print(obj["name"])
      # 執行obj['key']時會執行我
      # oldwang
      
      obj["name"] = "oldniu"
      print(obj["name"])
      # 執行obj['key'] = value 時會執行我
      # 執行obj['key']時會執行我
      # oldniu
      
      print(obj.__dict__)
      del obj["name"]
      print(obj.__dict__)
      # {'name': 'oldniu', 'age': 20}
      # 執行del['key']時會執行我
      # {'age': 20}
    2. __del__

      析構方法,當對象在內存中被釋放時,自動觸發執行。

      注:此方法通常無須定義,由於Python是一門高級語言,程序員在使用時無需關心內存的分配和釋放,由於此工做都是交給Python解釋器來執行,因此,析構函數的調用是由解釋器在進行垃圾回收時自動觸發執行的。

      class FileHandle:
          def __init__(self, file_path):
              self.f = open(file_path, mode="r", encoding="utf-8")
      
          def read(self):
              return self.f.read(1024)
      
          def __del__(self):
              # 在程序執行完時釋放文件句柄
              self.f.close()
      
      f = FileHandle("file/userinfo")
      print(f.read())
    3. __new__

      # 單例類
      class Single:
          __isinstance = None
      
          def __new__(cls, *args, **kwargs):
              if not cls.__isinstance:
                  cls.__isinstance = object.__new__(cls)
                  return cls.__isinstance
              return cls.__isinstance
      
      one = Single()
      two = Single()
      print(one is two) # True
    4. __call__

      對象後面加括號,觸發執行。

      注:構造方法的執行是由建立對象觸發的,即:對象 = 類名() ;而對於 call 方法的執行是由對象後加括號觸發的,即:對象() 或者 類()()

      class Foo:
          def __call__(self, *args, **kwargs):
              print("執行__call__")
      
      f = Foo()
      f()           # 執行__call__
      
      # 還能夠這樣寫
      Foo()()
    5. __len__

      class Foo:
          def __init__(self, name, age):
              self.name = name
              self.age =age
      
          def __len__(self):
              return len(self.__dict__)
      
      f = Foo("dogfa", 18)
      print(len(f)) # 2
    6. __hash__

      class A:
          def __init__(self):
              self.a = 1
              self.b = 2
      
          def __hash__(self):
              return hash(str(self.a)+str(self.b))
      a = A()
      print(hash(a))
    7. __eq__

      class A:
          def __init__(self):
              self.a = 1
              self.b = 2
      
          def __eq__(self,obj):
              if  self.a == obj.a and self.b == obj.b:
                  return True
      a = A()
      b = A()
      print(a == b) # True

3、其它

# 有一個員工類,1000個員工對象,對象屬性有姓名,性別,年齡,部門,
# 按姓名,性別對1000個對象去重
class Employee:
    def __init__(self, name, age, gender, department):
        self.name = name
        self.age = age
        self.gender = gender
        self.department = department
        
    def __hash__(self):
        return hash("{0}{1}".format(self.name, self.gender))
        
    def __eq__(self, other):
        if self.name == other.name and self.gender == other.gender:
            return True
            
employee_list = []

for i in range(250):
    employee_list.append(Employee("dogfa", i, "male", "python" + str(i)))
    
for i in range(250):
    employee_list.append(Employee("djb", i, "female", "php" + str(i)))
    
for i in range(250):
    employee_list.append(Employee("oldniu", i, "male", "java" + str(i)))
    
for i in range(250):
    employee_list.append(Employee("cdj", i, "female", "go" + str(i)))
    
for employee_obj in set(employee_list):
    print(employee_obj.__dict__)
相關文章
相關標籤/搜索