24262

Dynamically adding a property to a class

This has been previously asked on Stack Overflow, but none of the answers seem to address exactly what I need to do. In my case, I want these dynamically-added properties to be a shortcut to store and read values from a database, so unfortunately it's not as easy as in this answer (where a lambda function was used) or this one (where values where stored in a dictionary): I must call other methods of the class.

This is my attempt:

import operator class Foo(object): def get_value(self, name): # read and return value from database return -1 def set_value(self, name, value): # store value in database pass def add_metadata_property(name): getter = operator.methodcaller('get_value', name) setter = operator.methodcaller('set_value', name) # gets value at runtime setattr(Foo, name, property(getter, setter)) add_metadata_property('spam') f = Foo() f.spam # works! f.spam = 2

The last line, however, raises:

Traceback (most recent call last): File "<stdin>", line 27, in <module> TypeError: methodcaller expected 1 arguments, got 2

Any ideas on how to achieve this?

Answer1:

I don't know why you use operator.methodcaller here. When you call f.spam=2, it will invoke setter. setter = operator.methodcaller('set_value', name) means setter(r) = r.set_value(name). Make no sense in your case.

I suggest you write this way, using @classmethod:

class Foo(object): @classmethod def get_value(self, name): # read and return value from database return -1 @classmethod def set_value(self, name, value): # store value in database pass def add_metadata_property(name): setattr(Foo, name, property(Foo.get_value, Foo.set_value)) add_metadata_property('spam') f = Foo() f.spam # works! f.spam = 2

If this helped you, please confirm it as the answer. Thanks!

Answer2:

Modifying class template looks a bit odd for me. I would suggest to overload __getattr__() and __setattr__() methods in your case.

class Foo: def __getattr__(self, name): print('read and return value from database for ', name) return 123 def __setattr__(self, name, value): print('store value', value, 'for', name, 'in database')

Recommend

  • Python multiple inheritance name clashes [closed]
  • Use of enable_if to match only classes which have a certain static data member, and that has only sp
  • sql if statement checking for null parameter
  • retrofit.RetrofitError: 404 Not Found
  • Apache Lucene - Improving the results of Spell Checker
  • What's a fast (non-loop) way to apply a dict to a ndarray (meaning use elements as keys and rep
  • How to use ResourceDictionary in Windows Phone class library project
  • Dynamically set properties from Dictionary in Swift
  • Add spaces between words in spaceless string
  • Convert two columns Pandas data frame to dictionary of list with first column as keys
  • Find longest path less than or equal to given value of an acyclic, directed graph in Python
  • How do I bind multiple properties in an Android layout element
  • Efficient User-Agent Regex to find Safari in Python
  • Keep this build forever option - Jenkins
  • Converting a WriteableBitmap image ToArray in UWP
  • Typescript - Unable to get 'import' statement to function
  • Is there any way to access browser form field suggestions from JavaScript?
  • swift auto completion not working in Xcode6-Beta
  • Finding past revisions of files in StarTeam w/ .NET SDK / C#
  • Running a C# exe file
  • Hazelcast - OperationTimeoutException
  • Why winpcap requires both .lib and .dll to run?
  • Return words with double consecutive letters
  • Cannot Parse HTML Data Using Android / JSOUP
  • Python: how to group similar lists together in a list of lists?
  • Load html files in TinyMce
  • C# - Getting references of reference
  • Java static initializers and reflection
  • Change div Background jquery
  • How does Linux kernel interrupt the application?
  • unknown Exception android
  • Busy indicator not showing up in wpf window [duplicate]
  • Running Map reduces the dimensions of the matrices
  • Binding checkboxes to object values in AngularJs
  • Observable and ngFor in Angular 2
  • Unable to use reactive element in my shiny app
  • Why do underscore prefixed variables exist?
  • Net Present Value in Excel for Grouped Recurring CF
  • jQuery Masonry / Isotope and fluid images: Momentary overlap on window resize
  • How to load view controller without button in storyboard?