python - 如何使用 __new__ 将多个参数传递给一个类?
问题描述
我试图理解 __new__ 并且我对 OOP python 还很陌生。我有这个代码...
import csv
from csv import DictReader
import logging
import typing as T
class MaxLength(str):
def __new__(cls, field: str):
# how do i pass this dynamically in the PCW obj
maximum = 4
if len(field) > maximum:
raise ValueError('invalid length of fields at: ' + field)
return super().__new__(cls, field)
class PCW(T.NamedTuple):
length_checker: MaxLength
@classmethod
def from_row(cls, row: dict):
return cls(**{key: type_(row[key]) for key, type_ in cls._field_types.items()})
def validate_csv(reader: DictReader) -> bool:
for row in reader:
try:
PCW.from_row(row)
except Exception as e:
logging.error('type: {} msg: {}'.format(type(e), e))
return False
return True
input_file = validate_csv(csv.DictReader(open("test.csv")))
这可行,但我希望能够maximum
作为参数传入,以便这会改变。IE:
class PCW(T.NamedTuple):
length_checker: MaxLength(maximum=4)
...
input_file = validate_csv(csv.DictReader(open("test.csv")))
我想我已经掉进了兔子洞。这是可能的还是我忽略/误解了什么?
解决方案
一种方法是使用object.__init_subclass__()
Python 3.6 中添加的类方法。使用它需要子类化你的MaxLength
子类。
这就是我的意思:
import csv
from csv import DictReader
import logging
import typing as T
class MaxLength(str):
maximum = 8
@classmethod
def __init_subclass__(cls, **kwargs):
maximum = kwargs.pop('maximum', cls.maximum)
super().__init_subclass__(**kwargs)
cls.maximum = maximum
def __new__(cls, field: str):
if len(field) > cls.maximum:
raise ValueError('invalid length of fields at: ' + field)
return super().__new__(cls, field)
class PCW(T.NamedTuple):
# class PCWMaxLength(MaxLength):
class PCWMaxLength(MaxLength, maximum=4): # Override default maximum.
pass
length_checker: PCWMaxLength
@classmethod
def from_row(cls, row: dict):
return cls(**{key: type_(row[key]) for key, type_ in cls._field_types.items()})
# Display value assigned to nested class' constant.
print(f'PCWMaxLength.maximum: {PCWMaxLength.maximum}') # -> PCWMaxLength.maximum: 4
def validate_csv(reader: DictReader) -> bool:
for row in reader:
try:
PCW.from_row(row)
except Exception as e:
logging.error('type: {} msg: {}'.format(type(e), e))
return False
return True
否则,我认为您将需要进行一些实际的元类编程……</p>
推荐阅读
- python - Django在重定向后得到表单错误
- excel - 是否可以将工作表中的多个范围作为 .emf 图片嵌入到 Outlook 邮件正文中?
- python-3.x - 将 mp4 文件保存到 csv 以训练数据
- html - sceditor如何将bbcode解析回html?
- r - 如何在 data.table 列表上应用聚合和 rbind?
- excel - 将“模板”工作表复制到其他工作表
- javascript - 从 url 源打印 docx 文件
- c# - 如何在 CollectionView 中使用 FindByName
- angular - 为什么输入没有从 FormArray 显示
- python - 改变 JSON 序列化对象的形状 Django REST 框架