WhatisSober
WhatisSober

Reputation: 988

Dynamic methods based on a dict in python

I am working on creating a python module for getting stocks data.

I have a dictionary:

{'StockSymbol': 'AMD', 'LastTradeTime': '4:00PM EST', 'ChangePercent': '+0.58', 'ID': '327', 'LastTradeDateTimeLong': 'Mar 10, 4:00PM EST', 'Index': 'NASDAQ', 'LastTradeWithCurrency': '13.91', 'LastTradeDateTime': '2017-03-10T16:00:02Z', 'LastTradePrice': '13.91', 'LastTradeSize': '0', 'PreviousClosePrice': '13.33'}

Currently I have 11 methods such as:

class Stock(object):

    def getSymbol():
      return self.data['StockSymbol']

    def getLastTradeTime():
      return self.data['LastTradeTime']

    ........

I use it as:

google = Stock('GOOG')
print(google.getLastTradeTime()) //4:00PM EST

My question is, Is it possible to generate these methods dynamically?

So I could do google.getLastTradeSize() etc without defining them.

Here is a Python fiddle: https://repl.it/GSG1

Upvotes: 0

Views: 184

Answers (1)

Menglong Li
Menglong Li

Reputation: 2255

In Python there's a design pattern called bunch, it works like this, I believe it can solve your problem:

class Bunch(dict):
    def __init__(self, *args, **kwargs):
        super(Bunch, self).__init__(*args, **kwargs)
        self.__dict__ = self


    def __getattribute__(self, item):
        try:
            return object.__getattribute__(self, item)
        except:
            return None

my_dict = {'StockSymbol': 'AMD', 'LastTradeTime': '4:00PM EST', 'ChangePercent': '+0.58', 'ID': '327',
           'LastTradeDateTimeLong': 'Mar 10, 4:00PM EST', 'Index': 'NASDAQ', 'LastTradeWithCurrency': '13.91',
           'LastTradeDateTime': '2017-03-10T16:00:02Z', 'LastTradePrice': '13.91', 'LastTradeSize': '0',
           'PreviousClosePrice': '13.33'}

obj = Bunch(**my_dict)
print obj.StockSymbol
print obj.LastTradeTime
print obj.key_not_exist

And we get:

AMD

4:00PM EST

None

So you don't have to define your so-called gettter method, like what you do in Java/C++;

PS: in a real project, you can also inherit from this Bunch class.

===== Another optional ======

you can use pythonic-toolbox, a 3rd party lib maintained by me, that contains many useful tools, demos.

For your case, I think DictObj is a good choicehere in this lib.

my_dict = {'StockSymbol': 'AMD', 'LastTradeTime': '4:00PM EST', 'ChangePercent': '+0.58', 'ID': '327',
           'LastTradeDateTimeLong': 'Mar 10, 4:00PM EST', 'Index': 'NASDAQ', 'LastTradeWithCurrency': '13.91',
           'LastTradeDateTime': '2017-03-10T16:00:02Z', 'LastTradePrice': '13.91', 'LastTradeSize': '0',
           'PreviousClosePrice': '13.33'}

from pythonic_toolbox.utils.dict_utils import DictObj

obj = DictObj(my_dict)
assert hasattr(obj, 'StockSymbol')
assert obj.StockSymbol == 'AMD'
assert 'StockSymbol' in obj
assert obj.pop('LastTradePrice') == '13.91'
assert 'LastTradePrice' not in obj  # 'LastTradePrice' is popped up, so obj don't have attribute LastTradePrice anymore

del obj.LastTradeSize
assert not hasattr(obj, 'LastTradeSize')  # besides pop key as a dict, you can also delete it like an attribute

obj.greetings = 'hello world'  # assign new key/attribute
assert obj['greetings'] == 'hello world'

If you don't want others to change your DictObj attributes(modify, del, add), you can also use FinalDictObj, by from pythonic_toolbox.utils.dict_utils import FinalDictObj

Upvotes: 3

Related Questions