【问题标题】:How do I use a keyword as a variable name?如何使用关键字作为变量名?
【发布时间】:2016-10-24 10:10:39
【问题描述】:

我有以下带有变量fromtorate 的类。 from 是一个关键字。如果我想在下面的init方法中使用它,正确的写法是什么?

更多上下文:该类明确需要from 变量,因为它是另一个开发人员用不同语言编写的POST 端点所需的json 的一部分。所以改变变量名是不可能的。

class ExchangeRates(JsonAware):
    def __init__(self, from, to, rate):
        self.from = from
        self.to = to
        self.rate = rate

JsonAware 代码:

class PropertyEquality(object):
    def __eq__(self, other):
        return (isinstance(other, self.__class__) and self.__dict__ == other.__dict__)

    def __ne__(self, other):
        return not self.__eq__(other)

    def __repr__(self):
        return '%s(%s)' % (self.__class__.__name__, ', '.join(['%s=%s' % (k, v) for (k, v) in self.__dict__.items()]))

class JsonAware(PropertyEquality):
    def json(self):
        return json.dumps(self, cls=GenericEncoder)

    @classmethod
    def from_json(cls, json):
        return cls(**json)

通用编码器代码:

class GenericEncoder(json.JSONEncoder):
    def default(self, obj):
        return obj.__dict__

【问题讨论】:

  • 您不能将其用作标识符,因为它是关键字。这就是关键字的意思!使用例如from_ 代替。
  • from 被使用了 3 次,它被标记为红色 3 次,我不需要使用 **kwargs 转义它们的关键字或其他东西吗?
  • 如果你愿意,你可以这样做:setattr(self, 'from', kwargs.get('from')),但你也必须通过字典传递它:rates = ExchangeRates(..., **{'from': whatever}),并且只能通过 getattr(rates, 'from') 访问它。重命名它很多不那么尴尬。参见例如stackoverflow.com/q/9746838/3001761
  • 标记为红色听起来像是一个 IDE 试图帮助作者 ;-) 我会听从 @jonrsharpe 的建议。
  • 您可以使用该上下文和minimal reproducible exampleJsonAware 是什么?)来扩展问题,可能有一些方法可以处理与键为关键字的 JSON 之间的解析。但是你绝对不能直接做。

标签: python keyword


【解决方案1】:

使用同义词。改用“来源”或“来源”。

【讨论】:

    【解决方案2】:

    如 cmets 中所述,from 是 Python 关键字,因此您不能将其用作变量名或属性名。因此,您需要使用替代名称,并在读取或写入 JSON 数据时进行转换。

    要进行输出转换,您可以为json.dumps 提供一个新的编码器;您可以通过覆盖 ExchangeRates.json 方法来做到这一点。要进行输入转换,请覆盖ExchangeRates.from_json

    这两种情况的策略相似:我们创建字典的副本(因此我们不会改变原始字典),然后我们创建一个具有所需名称和值的新键,然后删除旧键。

    这是一个快速演示,在 Python 2.6 和 3.6 上进行了测试:

    import json
    
    class PropertyEquality(object):
        def __eq__(self, other):
            return (isinstance(other, self.__class__) and self.__dict__ == other.__dict__)
    
        def __ne__(self, other):
            return not self.__eq__(other)
    
        def __repr__(self):
            return '%s(%s)' % (self.__class__.__name__, ', '.join(['%s=%s' % (k, v) for (k, v) in self.__dict__.items()]))
    
    class JsonAware(PropertyEquality):
        def json(self):
            return json.dumps(self, cls=GenericEncoder)
    
        @classmethod
        def from_json(cls, json):
            return cls(**json)
    
    class ExchangeRatesEncoder(json.JSONEncoder):
        def default(self, obj):
            d = obj.__dict__.copy()
            d['from'] = d['frm']
            del d['frm']
            return d
    
    class ExchangeRates(JsonAware):
        def __init__(self, frm, to, rate):
            self.frm = frm
            self.to = to
            self.rate = rate
    
        def json(self):
            return json.dumps(self, cls=ExchangeRatesEncoder)
    
        @classmethod
        def from_json(cls, json):
            d = json.copy()
            d['frm'] = d['from']
            del d['from']
            return cls(**d)
    
    # Test
    
    a = ExchangeRates('a', 'b', 1.23)
    print(a.json())
    
    jdict = {"from": "z", "to": "y", "rate": 4.56, }
    
    b = ExchangeRates.from_json(jdict)
    print(b.json())    
    

    典型输出

    {"from": "a", "to": "b", "rate": 1.23}
    {"from": "z", "to": "y", "rate": 4.56}
    

    【讨论】:

    • 其他语言,例如 C#,使用 @ 符号解决这个问题,例如@string。在 python 中使用它会很好,例如@lambda.
    • @EduardoPignatelli 在 Python 中,@ 符号用于创建函数或类 decoratorPEP 8 与保留字或内置名称冲突的名称约定是附加一个尾随下划线,如 Psionman 的回答中所述。
    • @ 符号是任意的,它可以是任何东西。我发现下划线的问题是它实际上修改了变量的名称(即它将以下划线结尾)。
    【解决方案3】:

    为您的首选名称添加一个下划线:from_ 和 to_

    (见PEP 8

    class ExchangeRates(JsonAware):
        def __init__(self, from_, to_, rate):
            self.from = from_
            self.to = to_
            self.rate = rate
    

    【讨论】:

      猜你喜欢
      • 2019-12-01
      • 2014-01-01
      • 2021-09-11
      • 1970-01-01
      • 2011-09-02
      • 2017-01-15
      • 2017-12-05
      • 1970-01-01
      相关资源
      最近更新 更多