W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
你寫了很多僅僅用作數(shù)據(jù)結(jié)構(gòu)的類,不想寫太多煩人的 __init__()
函數(shù)
可以在一個(gè)基類中寫一個(gè)公用的 __init__()
函數(shù):
import math
class Structure1:
# Class variable that specifies expected fields
_fields = []
def __init__(self, *args):
if len(args) != len(self._fields):
raise TypeError('Expected {} arguments'.format(len(self._fields)))
# Set the arguments
for name, value in zip(self._fields, args):
setattr(self, name, value)
然后使你的類繼承自這個(gè)基類:
# Example class definitions
class Stock(Structure1):
_fields = ['name', 'shares', 'price']
class Point(Structure1):
_fields = ['x', 'y']
class Circle(Structure1):
_fields = ['radius']
def area(self):
return math.pi * self.radius ** 2
使用這些類的示例:
>>> s = Stock('ACME', 50, 91.1)
>>> p = Point(2, 3)
>>> c = Circle(4.5)
>>> s2 = Stock('ACME', 50)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "structure.py", line 6, in __init__
raise TypeError('Expected {} arguments'.format(len(self._fields)))
TypeError: Expected 3 arguments
如果還想支持關(guān)鍵字參數(shù),可以將關(guān)鍵字參數(shù)設(shè)置為實(shí)例屬性:
class Structure2:
_fields = []
def __init__(self, *args, **kwargs):
if len(args) > len(self._fields):
raise TypeError('Expected {} arguments'.format(len(self._fields)))
# Set all of the positional arguments
for name, value in zip(self._fields, args):
setattr(self, name, value)
# Set the remaining keyword arguments
for name in self._fields[len(args):]:
setattr(self, name, kwargs.pop(name))
# Check for any remaining unknown arguments
if kwargs:
raise TypeError('Invalid argument(s): {}'.format(','.join(kwargs)))
# Example use
if __name__ == '__main__':
class Stock(Structure2):
_fields = ['name', 'shares', 'price']
s1 = Stock('ACME', 50, 91.1)
s2 = Stock('ACME', 50, price=91.1)
s3 = Stock('ACME', shares=50, price=91.1)
# s3 = Stock('ACME', shares=50, price=91.1, aa=1)
你還能將不在 _fields
中的名稱加入到屬性中去:
class Structure3:
# Class variable that specifies expected fields
_fields = []
def __init__(self, *args, **kwargs):
if len(args) != len(self._fields):
raise TypeError('Expected {} arguments'.format(len(self._fields)))
# Set the arguments
for name, value in zip(self._fields, args):
setattr(self, name, value)
# Set the additional arguments (if any)
extra_args = kwargs.keys() - self._fields
for name in extra_args:
setattr(self, name, kwargs.pop(name))
if kwargs:
raise TypeError('Duplicate values for {}'.format(','.join(kwargs)))
# Example use
if __name__ == '__main__':
class Stock(Structure3):
_fields = ['name', 'shares', 'price']
s1 = Stock('ACME', 50, 91.1)
s2 = Stock('ACME', 50, 91.1, date='8/2/2012')
當(dāng)你需要使用大量很小的數(shù)據(jù)結(jié)構(gòu)類的時(shí)候,相比手工一個(gè)個(gè)定義 __init__()
方法而已,使用這種方式可以大大簡(jiǎn)化代碼。
在上面的實(shí)現(xiàn)中我們使用了 setattr()
函數(shù)類設(shè)置屬性值,你可能不想用這種方式,而是想直接更新實(shí)例字典,就像下面這樣:
class Structure:
# Class variable that specifies expected fields
_fields= []
def __init__(self, *args):
if len(args) != len(self._fields):
raise TypeError('Expected {} arguments'.format(len(self._fields)))
# Set the arguments (alternate)
self.__dict__.update(zip(self._fields,args))
盡管這也可以正常工作,但是當(dāng)定義子類的時(shí)候問(wèn)題就來(lái)了。當(dāng)一個(gè)子類定義了 __slots__
或者通過(guò)property(或描述器)來(lái)包裝某個(gè)屬性,那么直接訪問(wèn)實(shí)例字典就不起作用了。我們上面使用 setattr()
會(huì)顯得更通用些,因?yàn)樗策m用于子類情況。
這種方法唯一不好的地方就是對(duì)某些IDE而已,在顯示幫助函數(shù)時(shí)可能不太友好。比如:
>>> help(Stock)
Help on class Stock in module __main__:
class Stock(Structure)
...
| Methods inherited from Structure:
|
| __init__(self, *args, **kwargs)
|
...
>>>
可以參考9.16小節(jié)來(lái)強(qiáng)制在 __init__()
方法中指定參數(shù)的類型簽名。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: