Skip to content

Instantly share code, notes, and snippets.

@hdeshev
Forked from skanev/set_attributes.py
Created August 24, 2012 12:12
Show Gist options
  • Save hdeshev/3449924 to your computer and use it in GitHub Desktop.
Save hdeshev/3449924 to your computer and use it in GitHub Desktop.
Set arguments passed to the constructor as attributes
import inspect
from functools import wraps
def set_attributes(constructor):
@wraps(constructor)
def wrapped(self, *args, **kwargs):
names = inspect.getargspec(constructor).args
for (key, value) in dict(zip(names[1:], args)).items():
setattr(self, key, value)
for (key, value) in kwargs.items():
setattr(self, key, value)
return constructor(self, *args, **kwargs)
return wrapped
import unittest
class SetAttributesTest(unittest.TestCase):
def test_positional_arguments(self):
class Person:
@set_attributes
def __init__(self, name, age, gender):
pass
self.assertEqual('John Doe', Person('John Doe', None, None).name)
self.assertEqual(33, Person(None, 33, None).age)
self.assertEqual('male', Person(None, None, 'male').gender)
def test_keyword_arguments(self):
class Person:
@set_attributes
def __init__(self, **kwargs):
pass
self.assertEqual('John Doe', Person(name='John Doe').name)
def test_invoke_setters(self):
class Person:
@set_attributes
def __init__(self, age):
pass
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age * 2
self.assertEqual(20, Person(10).age)
# This is a fairly simple way to do it, but I dislike it:
class Person:
def __init__(self, name, age, location):
self.__dict__.update({k: v for (k, v) in locals().items() if k != 'self'})
person = Person('Stefan', 26, 'Sofia')
print(person.name)
print(person.age)
print(person.location)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment