Python attrs库:使用其他属性定义attr.ib(default =)

时间:2017-03-08 13:29:21

标签: python attr

我正在使用惊人的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没有看到floatdate,而是_CountingAttr对象,因此我得到了AttributeError (以及TypeError的{​​{1}}。由于我无法引用some_number * 100,我该怎么做?

2 个答案:

答案 0 :(得分:2)

目前,使用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问题跟踪器的信用指示我指向正确的方向。

答案 1 :(得分:0)

您也可以在没有const embed = new Discord.MessageEmbed().setColor("#E96A00"); switch (pageNumber) { //if you get it from msg.content it will be a string unless you parse it case "1": embed .setTitle("Command List: Basic") .addFields( { name: '‎', value: '‎' }, { name: '**r!help**', value: 'Shows a list of all the commands.' }, { name: '**r!invite**', value: 'Get the invite link for this bot.' }, { name: '**r!hello (shutting down soon)**', value: 'Just a simple hello.' }, ) .setFooter('Ryam v1b • Help Menu'); break; case "2": embed .setTitle('Commandlist: Fun') .addField( { name: '‎', value: '‎' }, { name: '**r!yeet**', value: 'Yeet peoples you mention, just for fun.' }, { name: '**r!gn**', value: 'Says goodnight to the mentioned user. Respect them.' }, { name: '**r!pump**', value: 'Shoot a pump to mentioned user and see how many you damaged them.' }, { name: '**r!snipe**', value: 'Snipe those scared kids and see how much you damaged them.' }, { name: '**r!fullsweat**', value: 'Full sweat on a mentioned user and see what you did.' }, ); break; case "3": embed .setTitle('Commandlist: Admin') .addFields( { name: '‎', value: '‎' }, { name: '**r!ping**', value: 'Test command.' }, { name: '**r!server**', value: 'Shows the name of the server this bot is on.' }, { name: '**r!clear**', value: 'Delete/clear messages mentioned.' }, { name: '**r!avatar**', value: 'Shows the avatar of that person.' }, ); break; } msg.channel.send(embed); 的情况下进行操作。

只需使用__attrs_post_init__

default = attr.Factory(lambda self: ..., takes_self=True)