溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Python類的內(nèi)置方法

發(fā)布時(shí)間:2020-08-04 00:07:06 來(lái)源:網(wǎng)絡(luò) 閱讀:673 作者:LJ_baby 欄目:編程語(yǔ)言

本章介紹一下python類中的一些內(nèi)置方法。內(nèi)置的方法有很多,有些內(nèi)置方法在object類中已經(jīng)定義,子類可以拿來(lái)直接使用,也可以重寫(xiě),但是有些內(nèi)置方法object類中沒(méi)有,比如 __len__ 方法(len()方法會(huì)調(diào)用 對(duì)應(yīng)類中的 __len__ 方法),需要根據(jù)需求來(lái)進(jìn)行定義~

__str__和__repr__

對(duì)象的字符串顯示 會(huì)調(diào)用__str__ 或 __repr__ 方法,__str__ 和 __repr__ 方法在object中已經(jīng)定義,默認(rèn)都是輸出對(duì)象在內(nèi)存中的地址,有時(shí)候根據(jù)需求需要重寫(xiě)這兩個(gè)方法~

class Person:
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

    def __repr__(self):
        return '(%s,%s)' % (self.name, self.city)

    def __str__(self):
        return '(%s,%s)' % (self.name, self.age)

p = Person('Kitty', 19, 'HZ')
print(p)         # (Kitty,19),調(diào)用 __str__
print(str(p))   # (Kitty,19),調(diào)用 __str__
print(repr(p)) # (Kitty,HZ),調(diào)用 __repr__

print('%s' % p)   # (Kitty,19),調(diào)用 __str__
print('%r' % p)   # (Kitty,HZ),調(diào)用 __repr__

在交互式解釋其中,直接輸出對(duì)象,會(huì)調(diào)用 __repr__ 方法

>>> p = Person('Kitty', 19, 'HZ')
>>> p
(Kitty,HZ)

Tip:

  • str函數(shù),print函數(shù),%s 會(huì)調(diào)用 __str__ 方法;
  • repr函數(shù),交互式解釋器,%r 會(huì)調(diào)用 __repr__ 方法;
  • 若是 僅重寫(xiě)了__repr__ 方法,那么 str函數(shù),print函數(shù),%s 就會(huì)用__repr__ 方法來(lái)代替,但是反過(guò)來(lái) __str__ 方法 不會(huì)代替 __repr__ 方法~

__format__

用于將對(duì)象格式化輸出

class Person:
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

    def __format__(self, format_spec):
        fmt = {
            '-': '{obj.name}-{obj.age}-{obj.city}',
            '/': '{obj.name}/{obj.age}/{obj.city}'
        }[format_spec]
        return fmt.format(obj = self)

p = Person('Kitty', 19, 'HZ')

# format 函數(shù)會(huì)調(diào)用對(duì)象的綁定方法 __format__
print(format(p, '-'))  
print(format(p, '/'))

# 輸出結(jié)果:
Kitty-19-HZ
Kitty/19/HZ

__del__

析構(gòu)方法,當(dāng)對(duì)象在內(nèi)存中被釋放時(shí),會(huì)自動(dòng)觸發(fā)執(zhí)行。但是此方法一般無(wú)須定義,因?yàn)镻ython解釋器會(huì)來(lái)完成內(nèi)存的分配和釋放工作,所以,析構(gòu)方法的調(diào)用是由解釋器在進(jìn)行垃圾回收時(shí)自動(dòng)觸發(fā)執(zhí)行的。

class Person:
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

    def __del__(self):
        print('delete...')

p = Person('Kitty', 19, 'HZ')
del p

# 輸出結(jié)果:
delete...

item系列

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __getitem__(self, item):
        return self.__dict__[item]

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, item):
        self.__dict__.pop(item)

    def __delattr__(self, key):
        self.__dict__.pop(key)

p = Person('Kitty', 19)
print(p['name'])    # Kitty,調(diào)用 __getitem__ 方法

p['age'] = 18
print(p['age'])       # 18

p['city'] = 'HZ'       
print(p.__dict__)   # 調(diào)用 __setitem__ 方法
# {'name': 'Kitty', 'age': 18, 'city': 'HZ'}

del p['city']             # 調(diào)用 __delitem__ 方法
print(p.__dict__) 
# {'name': 'Kitty', 'age': 18}

del p.age               # 調(diào)用 __delattr__ 方法
print(p.__dict__)
# {'name': 'Kitty'}

__len__

len(obj) 會(huì)調(diào)用obj的 __len__ 方法

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __len__(self):
        return len(self.__dict__)

p = Person('Kitty', 19)
print(len(p))       # 2

__call__

對(duì)象后面加括號(hào),就會(huì)觸發(fā) __call__ 方法的執(zhí)行,即調(diào)用方式:對(duì)象() 或者 類()()

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def __call__(self):
        print('hello' + ' ' + self.__name)

p = Person('Kitty', 19)()     # hello Kitty
# p()

__new__

在類的是實(shí)例化過(guò)程中,第一個(gè)被調(diào)用的是 __new__方法。在對(duì)象的初始化之前首先要?jiǎng)?chuàng)建對(duì)象,__new__方法正是用來(lái)創(chuàng)建這個(gè)對(duì)象~
?;
類的實(shí)例化過(guò)程也可以通過(guò)如下語(yǔ)句來(lái)實(shí)現(xiàn):

>>> p = object.__new__(Person) 
>>> Person.__init__(p, 'Kitty', 18)
>>> p.name
'Kitty'

在Person類中重寫(xiě) __new__方法:

class Person:
    country = "China"
    def __new__(cls, name, age):
        print('__new__ called')
        return super(Person, cls).__new__(cls)

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def speak(self, word):
        print(word)

p = Person('Kitty', 18)          # 實(shí)例化對(duì)象
print('name : %s' % p.name)

# 輸出結(jié)果:
__new__ called
name : Kitty

可以看到 __new__ 方法 是先于 __init__ 方法被調(diào)用的~
類的實(shí)例化過(guò)程大致步驟如下:
1、p = Person('Kitty', 18) ,會(huì)調(diào)用 Person類的 __new__ 方法,并傳遞 name 和 age 參數(shù)
2、__new__ 方法 會(huì)創(chuàng)建一個(gè) Person類的對(duì)象并返回
3、最后利用這個(gè)對(duì)象調(diào)用類的 __init__ 方法 完成初始化,__init__ 方法的第一個(gè)參數(shù)是self,對(duì)象在調(diào)用 __init__ 方法時(shí)會(huì)將自己當(dāng)做參數(shù)傳遞給 這個(gè)self。

單例模式

重寫(xiě) __new__ 來(lái)實(shí)現(xiàn)單例模式~

class Person:
   def __new__(cls, *args, **kwargs):
       if not hasattr(cls, '_instance'):
           cls._instance = super(Person, cls).__new__(cls, *args, **kwargs)
       return cls._instance

p1 = Person()
p2 = Person()

print(p1)    # <__main__.Person object at 0x108eb6438>
print(p2)    # <__main__.Person object at 0x108eb6438>

對(duì)象的內(nèi)存地址相同,則表示為同一個(gè)對(duì)象~

__hash__和__eq__

在判斷兩個(gè)對(duì)象是否一致時(shí),往往會(huì)用到這兩個(gè)函數(shù)~

__hash__

class Person:
    def __init__(self, name, age):
        self.__name = name
        self.__age = age

    def __hash__(self):
        return hash(str(self.__name))

p = Person('Kitty', '19')
print(hash(p))

__eq__

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __eq__(self, obj):
        if self.name == obj.name and self.age == obj.age:
            return True

p1 = Person('Kitty', '19')
p2 = Person('Kitty', '19')
print(p1 == p2)     # True

?
集合(set)是一個(gè)無(wú)序不重復(fù)元素的序列。集合中只能存放不可變對(duì)象(可hash的)。在向 set 集合中添加對(duì)象時(shí),會(huì)通過(guò)調(diào)用對(duì)象的 __hash__ 和 __eq__ 這兩個(gè)方法來(lái)判斷集合中是否已經(jīng)存在一樣的對(duì)象~

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __hash__(self):
        print('調(diào)用了__hash__方法')
        return hash(self.name)
    def __eq__(self, obj):
        print('調(diào)用了__eq__方法')
        return self.name == obj.name and self.age == obj.age

    def __str__(self):
        return '(' + self.name + ', ' + self.age + ')'

p1 = Person('Tom', '19')     # 調(diào)用了__hash__方法
p2 = Person('Jeff', '20')      # 調(diào)用了__hash__方法
my_set = {p1, p2}

for i in my_set:
    print(i)              # (Jeff, 20), (Tom, 19)

在向 set 集合中添加對(duì)象時(shí),會(huì)首先調(diào)用對(duì)象的 __hash__ 若是 返回的 hash值不一樣,則認(rèn)為不是重復(fù)的對(duì)象,進(jìn)行添加~

p1 = Person('Tom', '19')      # 調(diào)用了__hash__方法
p2 = Person('Tom', '20')      # 調(diào)用了__hash__方法,調(diào)用了__eq__方法
my_set = {p1, p2}

for i in my_set:       # (Tom, 20), (Tom, 19)
    print(i)

若是返回的hash值有重復(fù)的,則會(huì)接著調(diào)用對(duì)象 __eq__ 方法,若 __eq__ 方法的返回值為False,則認(rèn)為不是重復(fù)對(duì)象,進(jìn)行添加,若返回為True,則不進(jìn)行添加~
?
所以總結(jié)一下:set結(jié)合的去重是通過(guò)調(diào)用對(duì)象的 __hash__ 和 __eq__ 這兩個(gè)方法共同實(shí)現(xiàn)的
1、首先調(diào)用對(duì)象的 __hash__方法,返回的hash值不存在重復(fù),則直接添加該對(duì)象;
2、當(dāng)返回的hash值存在重復(fù),接著再調(diào)用 __eq__ 方法,返回為False,添加對(duì)象,返回為True,不進(jìn)行添加~

.................^_^

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI