Python 属性库:使用其他属性定义 attr.ib(默认=)
Python attrs library: define attr.ib(default=) using other attributes
我正在使用令人惊叹的 attrs
库以一种非常优雅的方式定义许多对象属性,到目前为止它一直非常有效。
我目前遇到的唯一问题是有时我想通过引用其他 attr.ib()
属性来定义默认值。如果 name
的默认值是静态字符串,下面是一些代码 运行:
import attr
from attr.validators import instance_of
import datetime
@attr.s
class Something:
some_date = attr.ib(validator=instance_of(datetime.date))
some_number = attr.ib(convert=float)
name = attr.ib(validator=instance_of(str),
default="Generic Name {0} - {1}%".format(
some_date.strftime("%d-%b-%Y"),
some_number * 100)
)
something_instance = Something(some_date=datetime.date.today(), some_number=0.375)
问题是 name
没有看到 float
和 date
,而是 _CountingAttr
对象,因此我得到了 AttributeError
(和 TypeError
对应 some_number * 100
)。由于我也无法引用 self
,我该怎么做?
因此目前使用 default 关键字似乎无法做到这一点。但是,要达到相同的效果,可以使用 __attrs_post_init__
方法,该方法可用于在实例初始化后执行任意计算: http://attrs.readthedocs.io/en/stable/examples.html?highlight=attrs_post_init#other-goodies
在我的示例中,基本上可以归结为添加
def __attrs_post_init__(self):
if self.name is None:
self.name = "Generic Name {0} - {1}%".format(
self.some_date.strftime("%d-%b-%Y"),
self.some_number * 100)
归功于 attrs github 问题跟踪器,它为我指明了正确的方向。
你也可以不用 __attrs_post_init__
。
只需使用default = attr.Factory(lambda self: ..., takes_self=True)
import attr
from attr.validators import instance_of
import datetime
@attr.s
class Something:
some_date = attr.ib(validator=instance_of(datetime.date))
some_number = attr.ib(convert=float)
name = attr.ib(validator=instance_of(str),
default=attr.Factory(lambda self: "Generic Name {0} - {1}%".format(
self.some_date.strftime("%d-%b-%Y"),
self.some_number * 100)
), takes_self=True)
something_instance = Something(some_date=datetime.date.today(), some_number=0.375)
我正在使用令人惊叹的 attrs
库以一种非常优雅的方式定义许多对象属性,到目前为止它一直非常有效。
我目前遇到的唯一问题是有时我想通过引用其他 attr.ib()
属性来定义默认值。如果 name
的默认值是静态字符串,下面是一些代码 运行:
import attr
from attr.validators import instance_of
import datetime
@attr.s
class Something:
some_date = attr.ib(validator=instance_of(datetime.date))
some_number = attr.ib(convert=float)
name = attr.ib(validator=instance_of(str),
default="Generic Name {0} - {1}%".format(
some_date.strftime("%d-%b-%Y"),
some_number * 100)
)
something_instance = Something(some_date=datetime.date.today(), some_number=0.375)
问题是 name
没有看到 float
和 date
,而是 _CountingAttr
对象,因此我得到了 AttributeError
(和 TypeError
对应 some_number * 100
)。由于我也无法引用 self
,我该怎么做?
因此目前使用 default 关键字似乎无法做到这一点。但是,要达到相同的效果,可以使用 __attrs_post_init__
方法,该方法可用于在实例初始化后执行任意计算: http://attrs.readthedocs.io/en/stable/examples.html?highlight=attrs_post_init#other-goodies
在我的示例中,基本上可以归结为添加
def __attrs_post_init__(self):
if self.name is None:
self.name = "Generic Name {0} - {1}%".format(
self.some_date.strftime("%d-%b-%Y"),
self.some_number * 100)
归功于 attrs github 问题跟踪器,它为我指明了正确的方向。
你也可以不用 __attrs_post_init__
。
只需使用default = attr.Factory(lambda self: ..., takes_self=True)
import attr
from attr.validators import instance_of
import datetime
@attr.s
class Something:
some_date = attr.ib(validator=instance_of(datetime.date))
some_number = attr.ib(convert=float)
name = attr.ib(validator=instance_of(str),
default=attr.Factory(lambda self: "Generic Name {0} - {1}%".format(
self.some_date.strftime("%d-%b-%Y"),
self.some_number * 100)
), takes_self=True)
something_instance = Something(some_date=datetime.date.today(), some_number=0.375)