我們先暫且稱呼為特殊方法。
單下劃線開頭(_foo) | 雙下劃線開頭的(__foo) | 雙下劃線開頭和結尾的( __foo__) |
---|---|---|
代表不能直接訪問的類屬性,需通過類提供的接口進行訪問,不能用“from xxx import *”而導入; | 代表類的私有成員 | 代表python里特殊方法專用的標識,如 _init_()代表類的構造函數 |
文章目錄
- 1 __repr__方法
- 2 __str__ 方法
- 3 __str__ and __repr__ example
- 4 python 類中的self是是什么
- 5 python3中的__slots__
- 6. __call__方法
- 7. 對象表現形式(__bytes__)
- 8.str.format()的簡單用法
- 字段名:省略;數字;變量名
- 轉換字段: !s !r !a
1 __repr__方法
_repr__是類的內建方法,所有的類都是繼承自Object類,因此在外部調用時,需要使用repr函數,好比Node類通過重寫__repr_,從而重寫了repr。
這是文檔上標注的,因為理解不太貼切,所以還是放上官方介紹吧。
Return a string containing a printable representation of an object.
For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval(), otherwise the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object.
A class can control what this function returns for its instances by defining a repr() method.
class Node(object):def __init__(self, value, flag = 1):self._value = valueself._children = []self._flag = flagdef add_child(self, node):self._children.append(node)def __repr__(self):return 'Node({!r})'.format(self._value)if __name__ == '__main__':n1 = Node(0)print(n1)#Node(0)
2 str 方法
此方法返回對象的字符串表示形式。在對象上調用print()或str()函數時調用此方法。
這個方法必須返回String對象。如果我們沒有為類實現_str__()函數,那么使用內置的對象實現來實際調用_repr__()函數。
3 str and repr example
我們注意到無論是__str__還是__repr__方法,返回的都要求是str類型
class Person(object):name = ""age = 0def __init__(self, personName, personAge):self.name = personNameself.age = personAgedef __repr__(self):return '{name'+self.name + ',' + 'age:' + str(self.age) + '}'def __str__(self):return 'Person(name=' + self.name + ', age=' + str(self.age) + ')'p = Person('Pankaj', 34)
# __str__() example
print(p) #Person(name=Pankaj, age=34)
# print(p.__str__())#Person(name=Pankaj, age=34)
# s = str(p)
# print(s)#Person(name=Pankaj, age=34)
#
# # __repr__() example
# print(p.__repr__())
# print(type(p.__repr__()))
# print(repr(p))
we mentioned that if we don’t implement str function then the repr function is called. Just comment the str function implementation from Person class and print§ will print {name:Pankaj, age:34}.我們發現,__str__的優先級是大于__repr__的。
4 python 類中的self是是什么
self指的是類實例對象本身(注意:不是類本身)。
5 python3中的__slots__
當一個類需要創建大量實例時,可以通過__slots__聲明實例所需要的屬性,
例如,class Foo(object): slots = [‘foo’]。這樣做帶來以下優點:
- 更快的屬性訪問速度
- 減少內存消耗
使用__slots__也是有副作用的:
1. 每個繼承的子類都要重新定義一遍__slots__
2. 實例只能包含哪些在__slots__定義的屬性,這對寫程序的靈活性有影響,比如你由于某個原因新網給instance設置一個新的屬性,比如instance.a = 1, 但是由于a不在__slots__里面就直接報錯了,你得不斷地去修改__slots__或者用其他方法迂回的解決
3. 實例不能有弱引用(weakref)目標,否則要記得把__weakref__放進__slots__
另外參考:https://zhuanlan.zhihu.com/p/25930288
6. __call__方法
一個函數(甚至對象)之所以能執行,關鍵就在于 call() 方法。實際上 x(arg1, arg2,…) 只是 x.call(arg1, arg2, …) 的快捷寫法,因此我們甚至可以為自定義類添加 _call_ 方法,從而使得該類的實例也變成可調用的。例如如下代碼:
# 定義Role類
class Role:def __init__ (self, name):self.name = name# 定義__call__方法def __call__(self):print('執行Role對象')
r = Role('管理員')
# 直接調用Role對象,就是調用該對象的__call__方法
r()# 執行Role對象
上面程序中最后一行代碼使用調用函數的語法來調用對象,這看上去似乎是錯誤的,但由于該 Role 類提供了\ call 方法,因此調用對象的本質就是執行該對象的 _call_ 方法。運行上面代碼,將看到如下輸出結果:
對于程序中的函數,同樣既可使用函數的語法來調用它,也可把函數當成對象,調用它的 call 方法。例如如下示例代碼:
def foo ():print('--foo函數--')
# 下面示范了2種方式調用foo()函數
foo()
foo.__call__()
運行上面代碼,可以看到 foo() 和 foo.__call__() 的效果完全相同。
7. 對象表現形式(bytes)
在 Python 3 中,
- _repr_、_str_ 和 _format_ 都必須返回 Unicode 字符串(str 類型)。
- 只有_bytes_ 方法應該返回字節序列(bytes 類型)。
8.str.format()的簡單用法
字段名:省略;數字;變量名
‘name is {}, age is {}’.format(‘peter’,25)
‘name is {1}, age is {0}’.format(25, ‘peter’)
‘name is {name}, age is {age}’.format(name=‘peter’,age=‘25’)
轉換字段: !s !r !a
- s:傳遞參數之前先對參數調用 str()
- r:傳遞參數之前先對參數調用 repr()
- a:傳遞參數之前先對參數調用 ascii()
例子:
class Person:def __init__(self, name, age):self.name = nameself.age = agedef __repr__(self):return 'Person({0.name!r}, {0.age!r})'.format(self)def __str__(self):return '({0.name!s}, {0.age!s})'.format(self)person = Person('peter', 25)
'this person is {!r}'.format(person)
'this person is {!s}'.format(person)
'this person is {!a}'.format('皮特')# result
"this person is Person('peter', 25)"
'this person is (peter, 25)'
"this person is '\\u76ae\\u7279'"