如何获取 python3 数据类实例的索引?
How to get index of python3 dataclass instance?
我想限制数据类实例的最大数量并知道实例的索引。这是我想要的行为:
Veget('tomato', 2.4, 5)
Veget('salad', 3.5, 2)
Veget('carot', 1.2, 7)
for Veget in Veget.instances:
print(Veget)
Veget(index=0, name='tomato', price=2.4, quantity=5)
Veget(index=1, name='salad', price=3.5, quantity=2)
Veget(index=2, name='carot', price=1.2, quantity=7)
我尝试了以下方法,它确实处理了创建限制:
from dataclasses import dataclass
MAX_COUNT = 3
class Limited:
instances = []
def __new__(cls, *_):
if len(cls.instances) < MAX_COUNT:
newobj = super().__new__(cls)
cls.instances.append(newobj)
return newobj
else:
raise RuntimeError('Too many instances')
@dataclass
class Veget(Limited):
name: str
price: float
quantity: int
但打印时不会显示索引:
Veget(name='tomato', price=2.4, quantity=5)
Veget(name='salad', price=3.5, quantity=2)
Veget(name='carot', price=1.2, quantity=7)
对数据类施加隐式限制或要求某种验证通常是通过指定的 __post_init__
而不是使用对象继承来实现的。利用它的实现可能看起来像这样,在我看来这会更容易维护和理解:
from dataclasses import dataclass, field
MAX_COUNT = 3
VEGET_INDEX = []
@dataclass
class Veget:
index: int = field(init=False)
name: str
price: float
quantity: int
def __post_init__(self):
self.index = len(VEGET_INDEX)
if self.index >= MAX_COUNT:
raise RuntimeError("Too many instances")
VEGET_INDEX.append(self)
您也可以使用计数器而不是在 post init 例程中递增的列表,但参考列表似乎便于调试。无论如何,创建三个允许的实例并尝试创建第四个实例如下所示:
>>> Veget('tomato', 2.4, 5)
Veget(index=0, name='tomato', price=2.4, quantity=5)
>>> Veget('salad', 3.5, 2)
Veget(index=1, name='salad', price=3.5, quantity=2)
>>> Veget('carot', 1.2, 7)
Veget(index=2, name='carot', price=1.2, quantity=7)
>>> Veget('potato', 0.7, 3)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<string>", line 5, in __init__
File "<input>", line 17, in __post_init__
RuntimeError: Too many instances
我们要修改实例化行为
因此,我们需要使用 class 方法本质上创建一个构造函数。
from dataclasses import dataclass
MAX_COUNT = 3
VEGET_INDEX = []
@dataclass
class Veget:
name : str
price : float
quantity : int
@classmethod
def create(cls, name, price, quantity):
index = len(VEGET_INDEX)
if index >= MAX_COUNT:
raise RuntimeError("Too many instances")
print('ok')
the_new_thing = cls(name, price, quantity)
VEGET_INDEX.append(the_new_thing)
return the_new_thing
Veget.create('tomato', 2.4, 5)
Veget.create('salad', 3.5, 2)
Veget.create('carot', 1.2, 7)
Veget.create('potato', 0.7, 3)
ok
ok
ok
Traceback (most recent call last):
File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in <module>
start(fakepyfile,mainpyfile) File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start
exec(open(mainpyfile).read(), __main__.__dict__)
File "<string>", line 27, in <module>
File "<string>", line 17, in create
RuntimeError: Too many instances
[Program finished]
根据 OP 的要求,我们可以打印索引,
from dataclasses import dataclass, field
MAX_COUNT = 3
VEGET_INDEX = []
@dataclass
class Veget:
index: int = field(init=False)
name: str
price: float
quantity: int
def __post_init__(self):
self.index = len(VEGET_INDEX)
if self.index >= MAX_COUNT:
raise RuntimeError("Too many instances")
VEGET_INDEX.append(self)
Veget('tomato', 2.4, 5)
Veget('salad', 3.5, 2)
Veget('carot', 1.2, 7)
#Veget('potato', 0.7, 3)
for Veget in VEGET_INDEX :
print(Veget)
Veget(index=0, name='tomato', price=2.4, quantity=5)
Veget(index=1, name='salad', price=3.5, quantity=2)
Veget(index=2, name='carot', price=1.2, quantity=7)
[Program finished]
我想限制数据类实例的最大数量并知道实例的索引。这是我想要的行为:
Veget('tomato', 2.4, 5)
Veget('salad', 3.5, 2)
Veget('carot', 1.2, 7)
for Veget in Veget.instances:
print(Veget)
Veget(index=0, name='tomato', price=2.4, quantity=5)
Veget(index=1, name='salad', price=3.5, quantity=2)
Veget(index=2, name='carot', price=1.2, quantity=7)
我尝试了以下方法,它确实处理了创建限制:
from dataclasses import dataclass
MAX_COUNT = 3
class Limited:
instances = []
def __new__(cls, *_):
if len(cls.instances) < MAX_COUNT:
newobj = super().__new__(cls)
cls.instances.append(newobj)
return newobj
else:
raise RuntimeError('Too many instances')
@dataclass
class Veget(Limited):
name: str
price: float
quantity: int
但打印时不会显示索引:
Veget(name='tomato', price=2.4, quantity=5)
Veget(name='salad', price=3.5, quantity=2)
Veget(name='carot', price=1.2, quantity=7)
对数据类施加隐式限制或要求某种验证通常是通过指定的 __post_init__
而不是使用对象继承来实现的。利用它的实现可能看起来像这样,在我看来这会更容易维护和理解:
from dataclasses import dataclass, field
MAX_COUNT = 3
VEGET_INDEX = []
@dataclass
class Veget:
index: int = field(init=False)
name: str
price: float
quantity: int
def __post_init__(self):
self.index = len(VEGET_INDEX)
if self.index >= MAX_COUNT:
raise RuntimeError("Too many instances")
VEGET_INDEX.append(self)
您也可以使用计数器而不是在 post init 例程中递增的列表,但参考列表似乎便于调试。无论如何,创建三个允许的实例并尝试创建第四个实例如下所示:
>>> Veget('tomato', 2.4, 5)
Veget(index=0, name='tomato', price=2.4, quantity=5)
>>> Veget('salad', 3.5, 2)
Veget(index=1, name='salad', price=3.5, quantity=2)
>>> Veget('carot', 1.2, 7)
Veget(index=2, name='carot', price=1.2, quantity=7)
>>> Veget('potato', 0.7, 3)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<string>", line 5, in __init__
File "<input>", line 17, in __post_init__
RuntimeError: Too many instances
我们要修改实例化行为 因此,我们需要使用 class 方法本质上创建一个构造函数。
from dataclasses import dataclass
MAX_COUNT = 3
VEGET_INDEX = []
@dataclass
class Veget:
name : str
price : float
quantity : int
@classmethod
def create(cls, name, price, quantity):
index = len(VEGET_INDEX)
if index >= MAX_COUNT:
raise RuntimeError("Too many instances")
print('ok')
the_new_thing = cls(name, price, quantity)
VEGET_INDEX.append(the_new_thing)
return the_new_thing
Veget.create('tomato', 2.4, 5)
Veget.create('salad', 3.5, 2)
Veget.create('carot', 1.2, 7)
Veget.create('potato', 0.7, 3)
ok
ok
ok
Traceback (most recent call last):
File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in <module>
start(fakepyfile,mainpyfile) File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start
exec(open(mainpyfile).read(), __main__.__dict__)
File "<string>", line 27, in <module>
File "<string>", line 17, in create
RuntimeError: Too many instances
[Program finished]
根据 OP 的要求,我们可以打印索引,
from dataclasses import dataclass, field
MAX_COUNT = 3
VEGET_INDEX = []
@dataclass
class Veget:
index: int = field(init=False)
name: str
price: float
quantity: int
def __post_init__(self):
self.index = len(VEGET_INDEX)
if self.index >= MAX_COUNT:
raise RuntimeError("Too many instances")
VEGET_INDEX.append(self)
Veget('tomato', 2.4, 5)
Veget('salad', 3.5, 2)
Veget('carot', 1.2, 7)
#Veget('potato', 0.7, 3)
for Veget in VEGET_INDEX :
print(Veget)
Veget(index=0, name='tomato', price=2.4, quantity=5)
Veget(index=1, name='salad', price=3.5, quantity=2)
Veget(index=2, name='carot', price=1.2, quantity=7)
[Program finished]