1. 程式人生 > >python之isinstance和issubclass,反射,內建方法

python之isinstance和issubclass,反射,內建方法

isinstance和issubclass

isinstance(obj,cls)檢查是否obj是否是類 cls 的物件。物件與類之間的關係

class B:pass
class A(B):pass
a = A()
print(isinstance(a, A))        #結果:True
print(isinstance(a, B))  # 能夠檢測到繼承關係 結果:True
print(type(a) is A)           #結果:True
print(type(a) is B)   # type只單純的判斷類 結果:False

issubclass(sub, super)檢查sub類是否是 super 類的派生類,類與類之間的關係

issubclass(子類名,父類名) 如果返回True,說明有繼承關係

class B:pass
class C(B): pass
class D(C):pass
print(issubclass(C, D))
print(issubclass(D,C))
print(issubclass(B,C))
print(issubclass(C,B))
print(issubclass(D,B))

反射

python面向物件中的反射:通過字串的形式操作物件相關的屬性。python中的一切事物都是物件(都可以使用反射)

四個可以實現自省的函式,類中的反射 類可以獲取類中的屬性和方法

下列方法適用於類和物件(一切皆物件,類本身也是一個物件) 反射有四種方法:

hasattr:hasattr(object,name)判斷一個物件是否有name屬性或者name方法。有就返回True,沒有就返回False

getattr:獲取物件的屬性或者方法,如果存在則打印出來。hasattr和getattr配套使用

需要注意的是,如果返回的是物件的方法,返回出來的是物件的記憶體地址,如果需要執行這個方法,可以在後面新增一對()

setattr:給物件的屬性賦值,若屬性不存在,先建立後賦值

delattr:刪除該物件指定的一個屬性
具體來看一下:

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

在反射中有這四種,四種方法的例項

hasattr,getattr一起使用

class A:
    role = 'person'
    def funx(self):
        print('***'*self)
print(hasattr(A, 'role'))          #結果:True
print(hasattr(A, 'funx'))           #結果:True
ret = input('>>>>')
if hasattr(A, ret):
    print(getattr(A, ret))
elif hasattr(A, ret):
    func = getattr(A, ret)
    func(1)
class A:
    role = 'Person'
    def __init__(self):
        self.money = 500
    def func(self):
        print('*'*10)
 
a = A()
print(a.func)
getattr(a,'func')()
print(getattr(a,'money'))

*類使用類名稱空間中的名字,物件使用物件能用的方法和屬性,模組使用模組中的名#,import os ; getattr(os,‘rename’)(‘user’,‘user_info’)

import time   # 一個py檔案就是一個模組
time.time()
print(time.time())
print(getattr(time,'time')())
 
import os
os.rename('userinfo','user')
getattr(os,'rename')('user','user_info')

從自己所在的模組中使用自己名字

def login():
    print('執行login功能')
 
def register():
    print('執行register功能')
 
import sys  # 和python直譯器相關的內容都在sys裡
print(sys.modules['__main__'])
func = input('>>>')
if hasattr(sys.modules['__main__'],func):
    getattr(sys.modules['__main__'],func)()

類使用類名稱空間中的名字 # getattr(類名,‘名字’) # 物件使用物件能用的方法和屬性 # getattr(物件名,‘名字’) #
模組使用模組中的名字 # 匯入模組 # getattr(模組名,‘名字’) # import os ;
getattr(os,‘rename’)(‘user’,‘user_info’) # 從自己所在的模組中使用自己名字 # import
sys # getattr(sys.modules[‘main’],名字) # getattr一定要和hasattr配合使用<em
id="__mceDel" style=“background-color: #ffffff; font-family: “PingFang
SC”, “Helvetica Neue”, Helvetica, Arial, sans-serif; font-size: 14px”>

增刪(setattr,delattr)改 物件屬性

class A:
    def __init__(self,name):
        self.name = name
 
    def wahaha(self):
        print('wahahahahaha')
 
a = A('alex')
a.wahaha()
#a.age = 18
#print(a.__dict__)
setattr(a,'age',18)   # 給a物件新增一個屬性
print(a.__dict__)
setattr(a,'name','egon')
print(a.__dict__)
#del a.age
delattr(a,'age')
print(a.__dict__)

增刪改 方法

class A:
    def __init__(self,name):
        self.name = name
 
    def wahaha(self):
        print('wahahahahaha')
 
def qqxing(self):
    print('qqqqqxing')
 
a = A('alex')
setattr(A,'qqxing',qqxing)
setattr(a,'qqxing',qqxing)
print(a.__dict__)
a.qqxing(a)

內建方法

__ len__

有一個內建函式 和內建方法len()是唯一對應的關係,len() obj.len() 返回值是一致的len() 的結果是依賴 ***obj.***__ len__

class A:
    def __init__(self,name,age,sex,cls):
        self.name = name
        self.age = age
        self.sex = sex
        self.cls = cls
    def __len__(self):
        return len(self.__dict__)
a1 = A('aa',81,'男',2)
print(len(a1))

__ call__
物件後面加括號,觸發執行。

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

class Teacher():
    def __call__(self):
        print(123)
    def call(self):
        print(456)
t = Teacher()
t.call()          
t()             # 物件名() 相當於呼叫類內建的__call__

一個物件是否可呼叫 完全取決於這個物件對應的類是否實現了__call__
__ new__
構造方法
例項化的時候
創造物件的過程 new
init 初始化
設計模式 —— 單例模式
單例模式 就是 一個類 只能有一個例項

class B:
    __instance = None
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            obj = object.__new__(cls)
            cls.__instance = obj
        return cls.__instance
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def func(self):
        print(self.name)
a = B('alex',80)
b = B('egon',20)
print(a)
print(b)
print(a.name)
print(b.name)

__ del__
析構方法: 在刪除一個物件的時候做一些首尾工作

class A:
    def __init__(self):
        self.f = open('檔案','w')
    def __del__(self):
        self.f.close()
        print('執行我啦')
a = A()
del a
print(a)
print('aaa')

__ hash__字典的儲存 hash
hash() 的結果是依賴 obj.hash()

class A:
    def __init__(self,name,age,sex,cls):
        self.name = name
        self.age = age
        self.sex = sex
        self.cls = cls
    def __hash__(self):
        return hash(str(self.name) + str(self.age))
a1 = A('aa',31,'女',2)
print(hash(a1))

__ eq__
== 是由__eq__的返回值來決定的

class A:
    def __eq__(self, other):
        # if self.__dict__ == other.__dict__:
            return True

__ eq__()

a = A()
a.name = 'alex'
b = A()
b.name = 'egon'
print(a)
print(b)
print(a == b)

__ str__和__ repr__ __ format__
改變物件的字串顯示__str__,repr

當需要使用__str__的場景時找不到 str__就找__repr
當需要使用__repr__的場景時找不到__repr__的時候就找父類的repr
雙下repr是雙下str的備胎
str() 的結果是依賴 obj.str()
print(obj) 的結果是依賴 obj.str()
%s 的結果是依賴 obj.str() # 語法糖
repr() 的結果是依賴 obj.repr()
%r 的結果是依賴 obj.repr()
自定製格式化字串__format__

format_dict = {
    'nat': '{obj.name}-{obj.addr}-{obj.type}',
    'tna': '{obj.name}:{obj.addr}:{obj.type}',
    'ant': '{obj.name}/{obj.addr}/{obj.type}'
}
class School:
    def __init__(self, name, addr, type):
        self.name = name
        self.addr = addr
        self.type = type
    def __repr__(self):
        return 'school(%s, %s)' % (self.name, self.addr)
    def __str__(self):
        return '(%s,%s)'% (self.name, self.addr)
    def __format__(self, format_spec):
        if not format_spec or format_spec not in format_dict:
            format_spec = 'nat'
        fmt = format_dict[format_spec]
        return fmt.format(obj=self)
s1=School('oldboy1','北京','私立')
print('from repr: ',repr(s1))
print('from str: ',str(s1))
print(s1)
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))

‘’‘str函式或者print函式—>obj.str()
repr或者互動式直譯器—>obj.repr()
如果__str__沒有被定義,那麼就會使用__repr__來代替輸出
注意:這倆方法的返回值必須是字串,否則丟擲異常’’’
  %s 和%r
 %s執行的就是__str__

%r執行的就是__repr__

class B:
 
     def __str__(self):
         return 'str : class B'
 
     def __repr__(self):
         return 'repr : class B'
b=B()
print('%s'%b)
print('%r'%b)

item系列
__ getitem__ __ setitem__ __ delitem__

class Foo:
    def __init__(self,name):
        self.name=name
 
    def __getitem__(self,item):
        return  self.__dict__[item]
 
    def __setitem__(self, key, value):
        self.__dict__[key]=value
 
    def __delitem__(self, key):
        print('del obj[key]時,我執行')
        self.__dict__.pop(key)
 
f = Foo('alex')
print(f['name'])    # f.__getitem__('name')
f['age']  = 18      # 賦值
print(f.age)         # 自帶的語法
print(f['age'])     # 修改
f['age']  = 80
print(f['age'])     # 通過實現__getitem__得到的
del f['age']
print(f.age)         # 刪除

*** __ hash__***

class Foo:
    def __hash__(self):
        print('aaaaaaaaaa')
        return hash(self.name)
        # print('aaas')
f = Foo()
f.name = 'egon'
print(hash(f))  #hash方法是可以重寫的

__hash__