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