2.1.2 Python面向?qū)ο笾瓷湟约皟?nèi)置方法

點擊跳轉(zhuǎn)筆記總目錄

閱讀目錄

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年首次提出的晕鹊,主要是指程序可以訪問松却、檢測和修改它本身狀態(tài)或行為的一種能力(自省)溅话。這一概念的提出很快引發(fā)了計算機(jī)科學(xué)領(lǐng)域關(guān)于應(yīng)用反射性的研究晓锻。它首先被程序語言的設(shè)計領(lǐng)域所采用,并在Lisp和面向?qū)ο蠓矫嫒〉昧顺煽儭?br> ==2 python面向?qū)ο笾械姆瓷洌?= 通過字符串的形式操作對象相關(guān)的屬性。python中的一切事物都是對象(都可以使用反射)
四個可以實現(xiàn)自省的函數(shù)
下列方法適用于類和對象(一切皆對象飞几,類本身也是一個對象)
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 = '類的靜態(tài)變量'
    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','不存在啊')) #報錯

#設(shè)置屬性
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砚哆,strrepr

改變對象的字符串顯示str,__repr__
自定制格式化字符串format

#_*_coding:utf-8_*_

format_dict={
    'nat':'{obj.name}-{obj.addr}-{obj.type}',#學(xué)校名-學(xué)校地址-學(xué)校類型
    'tna':'{obj.type}:{obj.name}:{obj.addr}',#學(xué)校類型:學(xué)校名:學(xué)校地址
    'tan':'{obj.type}/{obj.addr}/{obj.name}',#學(xué)校類型/學(xué)校地址/學(xué)校名
}
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函數(shù)或者print函數(shù)--->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

析構(gòu)方法屑墨,當(dāng)對象在內(nèi)存中被釋放時躁锁,自動觸發(fā)執(zhí)行。

注:此方法一般無須定義卵史,因為Python是一門高級語言战转,程序員在使用時無需關(guān)心內(nèi)存的分配和釋放,因為此工作都是交給Python解釋器來執(zhí)行以躯,所以槐秧,析構(gòu)函數(shù)的調(diào)用是由解釋器在進(jìn)行垃圾回收時自動觸發(fā)執(zhí)行的。
==簡單示范==

class Foo:

    def __del__(self):
        print('執(zhí)行我啦')

f1=Foo()
del f1
print('------->')

#輸出結(jié)果
執(zhí)行我啦
------->


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]時,我執(zhí)行')
        self.__dict__.pop(key)
    def __delattr__(self, item):
        print('del obj.key時,我執(zhí)行')
        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__

對象后面加括號刁标,觸發(fā)執(zhí)行。
注:構(gòu)造方法的執(zhí)行是由創(chuàng)建對象觸發(fā)的址晕,即:對象 = 類名() 膀懈;而對于 call 方法的執(zhí)行是由對象后加括號觸發(fā)的,即:對象() 或者 類()()

class Foo:

    def __init__(self):
        pass
    
    def __call__(self, *args, **kwargs):

        print('__call__')


obj = Foo() ## 執(zhí)行 __init__
obj()       ## 執(zhí)行 __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))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末斩箫,一起剝皮案震驚了整個濱河市吏砂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌乘客,老刑警劉巖狐血,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異易核,居然都是意外死亡匈织,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缀匕,“玉大人纳决,你說我怎么就攤上這事∠缧。” “怎么了阔加?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長满钟。 經(jīng)常有香客問我胜榔,道長,這世上最難降的妖魔是什么湃番? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任夭织,我火速辦了婚禮,結(jié)果婚禮上吠撮,老公的妹妹穿的比我還像新娘尊惰。我一直安慰自己,他們只是感情好泥兰,可當(dāng)我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布弄屡。 她就那樣靜靜地躺著,像睡著了一般逾条。 火紅的嫁衣襯著肌膚如雪琢岩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天师脂,我揣著相機(jī)與錄音担孔,去河邊找鬼。 笑死吃警,一個胖子當(dāng)著我的面吹牛糕篇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播酌心,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼拌消,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了安券?” 一聲冷哼從身側(cè)響起墩崩,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侯勉,沒想到半個月后鹦筹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡址貌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年铐拐,在試婚紗的時候發(fā)現(xiàn)自己被綠了徘键。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡遍蟋,死狀恐怖吹害,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情虚青,我是刑警寧澤它呀,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站棒厘,受9級特大地震影響钟些,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜绊谭,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望汪拥。 院中可真熱鬧达传,春花似錦、人聲如沸迫筑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽脯燃。三九已至搂妻,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辕棚,已是汗流浹背欲主。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留逝嚎,地道東北人扁瓢。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像补君,于是被迫代替她去往敵國和親引几。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容