一、簡介 dataclasses是python新的內置庫,也是一種新的特性吧(對我來說吧,因為我很少用到) 具體內容官方文檔也有: 二、使用 在python中創建一個類,我們需要寫\_\_init\_\_方法進行初始化對象操作,需要對對象進一步說明的話,最好寫一個\_\_repr\_\_方法,這樣我 ...
一、簡介
dataclasses是python新的內置庫,也是一種新的特性吧(對我來說吧,因為我很少用到)
具體內容官方文檔也有:https://docs.python.org/3/library/dataclasses.html
二、使用
在python中創建一個類,我們需要寫__init__方法進行初始化對象操作,需要對對象進一步說明的話,最好寫一個__repr__方法,這樣我們直接輸出對象的話,方便理解這個對象是啥。寫兩三個這樣的類還好,多了的話,就覺得煩躁了,因為每寫個類,你都得需要寫__init__,__repr__這些方法,都是重覆性的操作。
class People:
def __init__(self, name, age):
self.name = name
self.age = age
def __repr__(self):
return f"Student-{self.name}"
# 實例一個name為zhuyu的People對象
zhuyu = People("zhuyu", 23)
print(zhuyu.name) # 輸出 zhuyu
print(zhuyu) # Student-zhuyu
下麵使用dataclasses去創建一個類,相對於上面這個類的寫法是不是顯得簡單很多,一些魔法方法不用我們自己去寫dataclasss會幫我們完成。
from dataclasses import dataclass
@dataclass # 重點這裡
class Goods:
"""商品類"""
name: str
price: float
milk = Goods("milk", 9.99)
print(milk.name) # milk
print(milk) # Goods(name='milk', price=9.99)
dataclass會幫我們重寫一個魔法方法,可能是你想要的,也可能是你不想要的,我們可以通過一些參數進行控制(哪些魔法不想重寫),繼續看dataclass函數,它是可以傳參數的,它的註釋也寫得很清楚了
def dataclass(_cls=None, *, init=True, repr=True, eq=True, order=False,
unsafe_hash=False, frozen=False):
"""Returns the same class as was passed in, with dunder methods
added based on the fields defined in the class.
Examines PEP 526 __annotations__ to determine fields.
If init is true, an __init__() method is added to the class. If
repr is true, a __repr__() method is added. If order is true, rich
comparison dunder methods are added. If unsafe_hash is true, a
__hash__() method function is added. If frozen is true, fields may
not be assigned to after instance creation.
"""
def wrap(cls):
return _process_class(cls, init, repr, eq, order, unsafe_hash, frozen)
# See if we're being called as @dataclass or @dataclass().
if _cls is None:
# We're called with parens.
return wrap
# We're called as @dataclass without parens.
return wrap(_cls)
init參數預設為True
,會預設幫你添加init方法,那麼你實例化該對象的話,就需要傳參數(如果需要參數傳遞話),為False
的話,實例對象就不用傳遞了
..................具體實現效果可以寫個小demo,去看看就行
當然之前我們在寫類的時候,init
方法中不單單隻是對屬性進行賦值,例如下麵這個demo
import uuid
def get_id():
return str(uuid.uuid4())
class A:
def __init__(self, name):
self.name = name
self.id = get_id() # id不需要當作參數傳來
self._init_config() # 執行其他一些初始化操作
def _init_config(self):
"""配置相關的操作"""
print("執行初始化操作")
print(self.name)
a = A("zhuyu")
print(a.id)
下麵我們通過dataclass來實現上面這個例子,通過重寫__post_init__
這個方法,在這個方法中做一個邏輯操作,它執行完__init__
方法之後就會調用__post_init__
這個方法
from dataclasses import dataclass
import uuid
def get_id():
return str(uuid.uuid4())
@dataclass
class A:
name: str
id: str = get_id() # id 通過調用一個函數生成,就不用傳入了
def _init_config(self):
"""配置相關的操作"""
print("執行初始化操作")
print(self.name)
def __post_init__(self):
self._init_config()
a = A("zhu")
print(a.id)
關於類的繼承,使用dataclass一樣也是可以繼承的
from dataclasses import dataclass
@dataclass
class A:
name: str
def __post_init__(self):
print('父類')
@dataclass
class B(A):
age: int
def __post_init__(self):
print('基類')
super().__post_init__()
b = B('name', 22)
繼續看field,這個函數的位置為from dataclasses import field
def field(*, default=MISSING, default_factory=MISSING, init=True, repr=True,
hash=None, compare=True, metadata=None):
"""Return an object to identify dataclass fields.
default is the default value of the field. default_factory is a
0-argument function called to initialize a field's value. If init
is True, the field will be a parameter to the class's __init__()
function. If repr is True, the field will be included in the
object's repr(). If hash is True, the field will be included in
the object's hash(). If compare is True, the field will be used
in comparison functions. metadata, if specified, must be a
mapping which is stored but not otherwise examined by dataclass.
It is an error to specify both default and default_factory.
"""
if default is not MISSING and default_factory is not MISSING:
raise ValueError('cannot specify both default and default_factory')
return Field(default, default_factory, init, repr, hash, compare,
metadata)
寫個demo看看這個怎麼使用
from dataclasses import field, dataclass
@dataclass
class A:
name: str = field(default='zhuyu')
@dataclass
class B:
name: str = field(init=True)
a = A()
b = B('zhuyu')
print(a.name) # zhuyu
print(b.name) # zhuyu
# init預設為true,說明你在初始化對象的時候,需要傳遞該參數(參考class B),但是field中從參數default 或者default_factory不為空的時候,就算init為true,也是可以不用傳遞參數(參考class A)
from dataclasses import field, dataclass
@dataclass
class A:
name: str = field()
age: int = field(repr=False)
@dataclass
class B:
name: str = field()
age: int = field(repr=True)
a = A('zhuyu', 22)
b = B('zhuyu', 23)
print(a) # A(name='zhuyu')
print(b) # B(name='zhuyu', age=23)
# repr預設為True,會將該欄位添加到__repr__中去,為False的話,則不會添加進去
......... 其他的一些參數,可以寫一些demo看看顯示效果
三、完。
後面會經常使用這樣的寫法吧,多瞭解python的新特性還是挺不錯的,typing模塊我看很多第三方庫中也在經常使用,自己也要多學習學習。
參考文章:https://www.jianshu.com/p/22c07d6839ed