How do I use a keyword as a variable name?

I have the following class with the variables from, to and rate. from is a keyword. If I want to use it in the init method below, what’s the correct way to write it?

More context: The class needs the from variable explicitly as it’s part of a json required by a POST endpoint written up by another developer in a different language. So changing the variable name is out of the question.

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

JsonAware code:

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)

GenericEncoder code:

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

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Add a single underscore to your preferred names: from_ and to_

(see PEP 8)

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

Method 2

As mentioned in the comments, from is a Python keyword so you can’t use it as a variable name, or an attribute name. So you need to use an alternative name, and do a conversion when reading or writing the JSON data.

To do the output conversion you can supply a new encoder for json.dumps; you can do that by overriding the ExchangeRates.json method. To do the input conversion, override ExchangeRates.from_json.

The strategy is similar in both cases: we create a copy of the dictionary (so we don’t mutate the original), then we create a new key with the desired name and value, then delete the old key.

Here’s a quick demo, tested on Python 2.6 and 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())

typical output

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

Method 3

Use a synonym. Try “origin” or “source” instead.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x