閱讀目錄
1,isinstance和issubclass
2,反射
- setattr
- delattr
- getattr
- hasattr
3,__str__和__repr__
4,__del__
5,item系列
- __getitem__
- __setitem__
- __delitem__
6,__new__
7,__call__
8,__len__
9,__hash__
10,__eq__
1,isinstance和issubclass
isinstance(obj,cls)檢查是否obj是否是類 cls 的物件
class Foo(object):
pass
obj = Foo()
isinstance(obj, Foo)
複製程式碼
issubclass(sub, super)檢查sub類是否是 super 類的派生類
class Foo(object):
pass
class Bar(Foo):
pass
issubclass(Bar, Foo)
複製程式碼
2,反射
1 什麼是反射 反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。這一概念的提出很快引發了電腦科學領域關於應用反射性的研究。它首先被程式語言的設計領域所採用,並在Lisp和麵向物件方面取得了成績。 2 python物件導向中的反射: 通過字串的形式操作物件相關的屬性。python中的一切事物都是物件(都可以使用反射) 四個可以實現自省的函式 下列方法適用於類和物件(一切皆物件,類本身也是一個物件) 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
複製程式碼
四個方法的使用演示
class Foo:
f = '類的靜態變數'
def __init__(self,name,age):
self.name=name
self.age=age
def say_hi(self):
print('hi,%s'%self.name)
obj=Foo('egon',73)
#檢測是否含有某屬性
print(hasattr(obj,'name'))
print(hasattr(obj,'say_hi'))
#獲取屬性
n=getattr(obj,'name')
print(n)
func=getattr(obj,'say_hi')
func()
print(getattr(obj,'aaaaaaaa','不存在啊')) #報錯
#設定屬性
setattr(obj,'sb',True)
setattr(obj,'show_name',lambda self:self.name+'sb')
print(obj.__dict__)
print(obj.show_name(obj))
#刪除屬性
delattr(obj,'age')
delattr(obj,'show_name')
delattr(obj,'show_name111')#不存在,則報錯
print(obj.__dict__)
複製程式碼
3,str__和__repr
改變物件的字串顯示__str__,__repr__ 自定製格式化字串__format__
#_*_coding:utf-8_*_
format_dict={
'nat':'{obj.name}-{obj.addr}-{obj.type}',#學校名-學校地址-學校型別
'tna':'{obj.type}:{obj.name}:{obj.addr}',#學校型別:學校名:學校地址
'tan':'{obj.type}/{obj.addr}/{obj.name}',#學校型別/學校地址/學校名
}
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 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)
'''
str函式或者print函式--->obj.__str__()
repr或者互動式直譯器--->obj.__repr__()
如果__str__沒有被定義,那麼就會使用__repr__來代替輸出
注意:這倆方法的返回值必須是字串,否則丟擲異常
'''
print(format(s1,'nat'))
print(format(s1,'tna'))
print(format(s1,'tan'))
print(format(s1,'asfdasdffd'))
複製程式碼
%s和%r
class B:
def __str__(self):
return 'str : class B'
def __repr__(self):
return 'repr : class B'
b=B()
print('%s'%b)
print('%r'%b)
複製程式碼
4,del
析構方法,當物件在記憶體中被釋放時,自動觸發執行。
注:此方法一般無須定義,因為Python是一門高階語言,程式設計師在使用時無需關心記憶體的分配和釋放,因為此工作都是交給Python直譯器來執行,所以,解構函式的呼叫是由直譯器在進行垃圾回收時自動觸發執行的。 簡單示範
class Foo:
def __del__(self):
print('執行我啦')
f1=Foo()
del f1
print('------->')
#輸出結果
執行我啦
------->
複製程式碼
5,item系列
__getitem__ __setitem__ __delitem__
class Foo:
def __init__(self,name):
self.name=name
def __getitem__(self, item):
print(self.__dict__[item])
def __setitem__(self, key, value):
self.__dict__[key]=value
def __delitem__(self, key):
print('del obj[key]時,我執行')
self.__dict__.pop(key)
def __delattr__(self, item):
print('del obj.key時,我執行')
self.__dict__.pop(item)
f1=Foo('sb')
f1['age']=18
f1['age1']=19
del f1.age1
del f1['age']
f1['name']='alex'
print(f1.__dict__)
複製程式碼
6,__new__
class A:
def __init__(self):
self.x = 1
print('in init function')
def __new__(cls, *args, **kwargs):
print('in new function')
return object.__new__(A, *args, **kwargs)
a = A()
print(a.x)
複製程式碼
單例模式
class Singleton:
def __new__(cls, *args, **kw):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls, *args, **kw)
return cls._instance
one = Singleton()
two = Singleton()
two.a = 3
print(one.a)
## 3
## one和two完全相同,可以用id(), , is檢測
print(id(one))
## 29097904
print(id(two))
## 29097904
print(one two)
## True
print(one is two)
複製程式碼
7,__call__
物件後面加括號,觸發執行。 注:構造方法的執行是由建立物件觸發的,即:物件 = 類名() ;而對於 call 方法的執行是由物件後加括號觸發的,即:物件() 或者 類()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() ## 執行 __init__
obj() ## 執行 __call__
複製程式碼
8,__len__
class A:
def __init__(self):
self.a = 1
self.b = 2
def __len__(self):
return len(self.__dict__)
a = A()
print(len(a))
複製程式碼
9,__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))
複製程式碼
10,__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)
複製程式碼
紙牌遊戲
class FranchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suits = ['紅心','方板','梅花','黑桃']
def __init__(self):
self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
for suit in FranchDeck.suits]
def __len__(self):
return len(self._cards)
def __getitem__(self, item):
return self._cards[item]
deck = FranchDeck()
print(deck[0])
from random import choice
print(choice(deck))
print(choice(deck))
複製程式碼
紙牌遊戲2
class FranchDeck:
ranks = [str(n) for n in range(2,11)] + list('JQKA')
suits = ['紅心','方板','梅花','黑桃']
def __init__(self):
self._cards = [Card(rank,suit) for rank in FranchDeck.ranks
for suit in FranchDeck.suits]
def __len__(self):
return len(self._cards)
def __getitem__(self, item):
return self._cards[item]
def __setitem__(self, key, value):
self._cards[key] = value
deck = FranchDeck()
print(deck[0])
from random import choice
print(choice(deck))
print(choice(deck))
from random import shuffle
shuffle(deck)
print(deck[:5])
複製程式碼
一道面試題
class Person:
def __init__(self,name,age,sex):
self.name = name
self.age = age
self.sex = sex
def __hash__(self):
return hash(self.name+self.sex)
def __eq__(self, other):
if self.name other.name and self.sex other.sex:return True
p_lst = []
for i in range(84):
p_lst.append(Person('egon',i,'male'))
print(p_lst)
print(set(p_lst))
複製程式碼