print out the class parameters on python - python

class FooTable(Base):
Id = Column(BIGINT, primary_key=True)
name = Column(VARCHAR(256), nullable=False)
username = Column(VARCHAR(256), nullable=False)
state = Column(VARCHAR(100), nullable=False)
city = Column(VARCHAR(256), nullable=False)
zip = Column(VARCHAR(100), nullable=False)
I want to print out the instantiation arguments of class Column. generally- python code to string. example:
for k, v in vars(FooTable).iteritems():
print k, get_class_attr(v)
>>> Id ["BIGINT", "primary_key=True"]
>>> name ["VARCHAR(256)", "nullable=False"]
...
I tried the inspect module, but found that it does not support it:
http://docs.python.org/library/inspect.html#inspect.getmembers
Thanks for any information

I'd suggest using __dict__ and then filterting its output as dir won't work with metaclasses either.
def filterFunction(field):
'''
This is a sample filtering function
'''
name, value = field
return not name.startswith("_")
for k, v in vars(FooTable).iteritems():
print k, filter(filterFunction, v.__dict__.items())
For that case for the following class
class X():
foo = "bar"
baz = True
Our filter
filter(filterFunction, X.__dict__.items())
would return
[('foo', 'bar'), ('baz', True)]
To get instantiation parameters, i'd check whether field name is in Column.__init__.im_self

Actually what you are asking for, doesn't make much sense. Burhan Khalid's answer is close, but not really. You want the actual arguments that the caller passed when instantiating
the class. Not the function's/constructor's signature.
But this is book keeping that the class' programmer should do on his own. And even then,
he wouldn't actually do that. He would configure each instance based on the passed
parameters.
e.g.
class Foo(object):
def __init__(self, *args, **kwargs):
self.is_cool = kwargs.get('whatever', False)
And then I would check the instance attribute:
f = Foo()
f.is_cool # False
and I would try to make sense of it, depending on what this means for my instance.
But I don't really care about the actual parameters passed. My instance will
configure itself based on what was passed.
You could of course write a class decorator that wraps any 3rd party Class and do
exactly what you need, but it is an overhead that doesn't seem justifiable in this case.

You can print the attributes of a class with:
print dir( Column )
This is if I correctly understand your question

attrs = [i for i in dir(obj) if not i.startswith('_')]
Keep in mind that attributes that begin with _ are generally considered "private". Here is a sample run:
>>> [i for i in dir(4) if not i.startswith('_')]
['conjugate', 'denominator', 'imag', 'numerator', 'real']
>>> [i for i in dir('') if not i.startswith('_')]
['capitalize', 'center', ... 'split', 'splitlines', ... 'upper', 'zfill']
>>> class Foo:
... a = 'Hello'
... def __init__(self):
... pass
... def hello(self):
... print 'Hello'
...
>>> [i for i in dir(Foo) if not i.startswith('_')]
['a', 'hello']

I think you are looking for this:
>>> class Foo:
... def bar(a,b,c):
... pass
...
>>> x = Foo()
>>> x.bar.func_code.co_varnames
('a', 'b', 'c')
Here is another attempt, and I think this does what you need; although its a bit convoluted.
>>> class Foo:
... a = 'b'
... def bar(y,z):
... pass
...
>>> funcs = [(i,getattr(Foo,i).func_code.co_varnames) for i in dir(Foo) \
... if hasattr(getattr(Foo,i),'func_code')]
>>>
>>> funcs
[('bar', ('y', 'z'))]
However if you want to know what arguments were passed to a class, then from the instance, use __dict__.
>>> class Foo:
... a = ''
... def __init__(self, b, c):
... self.a = b
... self.c = c
...
>>> funcs = [(i,getattr(Foo,i).func_code.co_varnames) for i in dir(Foo) if hasattr(getattr(Foo,i),'func_code')]
>>> funcs
[('__init__', ('self', 'b', 'c'))]
>>> i = Foo(1,2)
>>> i.__dict__
{'a': 1, 'c': 2}

Related

Python class members with dynamic names

I've seen a class in python which does something of this kind:
obj = Class( name = "somename" )
obj.somename = something
Namely the class initialisation created a member called as the argument string.
I cannot manage to reproduce this behaviour. Any ideas?
I managed to do something similar using globals()["name"] = value. But in this case the created object is son of the module not of the "Class" object. And it's callable as module.somename instead of obj.somename.
You can easily create a dynamically named member by using setattr:
>>> class Foo(object):
... def __init__(self, name):
... setattr(self, name, 42)
...
>>> f = Foo('bar')
>>> f.bar
42
>>> f.bar = 'hello'
>>> f.bar
'hello'
Note however, that just setting any attribute on an instance of a class is possible for any regular class (that doesn't define __slots__):
>>> class Qux(object):
... pass
...
>>> q = Qux()
>>> q.foobar = 'hello'
>>> q.foobar
'hello'
You can either create a dynamically named fixed value property like this:
class MyClass():
def __init__(self, attr):
self.__dict__[attr] = 'some_value'
Or create as many properties as the calling function wants:
class MyClass():
def __init__(self, *argv, **kwargs):
for key,value in kwargs.items():
self.__dict__[key] = value

Get name of the bound method from instance of the bound method object in Python

I have :
class A:
def a():
pass
After typing in the python command line:
Aobj = A()
aBoundMeth = getattr(Aobj, 'a')
My goal is to get the name of the method that aBoundMeth object represents. Is it possible to do it?
Thank you in advance.
Assuming that the name of the method is the string 'a' (in this case), You can use the __name__ attribute on the function object.
e.g.
>>> Aobj = A()
>>> aBoundMeth = getattr(Aobj, 'a')
>>> aBoundMeth.__name__
'a'
Note that this is the function name when it was created. You can make more references to the same function, but the name doesn't change. e.g.
>>> class A(object):
... def a(self):
... pass
... b = a
...
>>> Aobj = A()
>>> Aobj.a.__name__
'a'
>>> Aobj.b.__name__
'a'

Python: retrieve all properties of a class instance that uses the #property annotation

Is there an easy way to retrieve all properties of a class instance that use #property or property methods?
I have seen examples that use vars but that does not work a class like:
class Test(object):
CONSTANT='SKIP ME'
def __init__(self):
self.my = "my"
self.__wrapper = {Test.CONSTANT : "wrapped value"}
#property
def wrapped_value(self):
return self.__wrapper[Test.CONSTANT]
Desired output would be dictionary with key/value.
dict = {"my": "my",
"wrapped_value": "wrapped value",
"__wrapper" : <dict>
}
As an added plus is there a way to get it to skip class level variables?
A simple solution would be this:
instance = Test()
dict((p, getattr(instance, p))
for p in dir(instance)
if p not in dir(Test) or isinstance(getattr(Test, p), property))
It yields:
{'_Test__wrapper': {'SKIP ME': 'wrapped value'}, 'wrapped_value': 'wrapped value', 'my': 'my'}
property is a class. Just test the class members to see if they're an instance of it.
>>> class Foo(object):
... #property
... def bar(self):
... return self._bar
...
>>> [x for x in Foo.__dict__ if isinstance(Foo.__dict__[x], property)]
['bar']
>>> foo = Foo()
>>> [x for x in foo.__class__.__dict__ if isinstance(foo.__class__.__dict__[x], property)]
['bar']
>>> dict((x, getattr(foo, x)) for x in foo.__class__.__dict__ if isinstance(foo.__class__.__dict__[x], property))
{'bar': 42}
This will result in a dictionary of all properties of a class instance that use #property or property methods. It's similar to what others have said.
a = Test()
propdict = {} # or propdict = dict()
for attrname in dir(a.__class__):
if isinstance(getattr(a.__class__, attrname), property):
propdict[attrname] = getattr(a, attrname)
Then propdict would be {'wrapped_value': 'wrapped value'}, as wrapped_value is the only property of your Test class.

Getting the class name of an instance

How do I find out the name of the class used to create an instance of an object in Python?
I'm not sure if I should use the inspect module or parse the __class__ attribute.
Have you tried the __name__ attribute of the class? ie type(x).__name__ will give you the name of the class, which I think is what you want.
>>> import itertools
>>> x = itertools.count(0)
>>> type(x).__name__
'count'
If you're still using Python 2, note that the above method works with new-style classes only (in Python 3+ all classes are "new-style" classes). Your code might use some old-style classes. The following works for both:
x.__class__.__name__
Do you want the name of the class as a string?
instance.__class__.__name__
type() ?
>>> class A:
... def whoami(self):
... print(type(self).__name__)
...
>>>
>>> class B(A):
... pass
...
>>>
>>>
>>> o = B()
>>> o.whoami()
'B'
>>>
class A:
pass
a = A()
str(a.__class__)
The sample code above (when input in the interactive interpreter) will produce '__main__.A' as opposed to 'A' which is produced if the __name__ attribute is invoked. By simply passing the result of A.__class__ to the str constructor the parsing is handled for you. However, you could also use the following code if you want something more explicit.
"{0}.{1}".format(a.__class__.__module__,a.__class__.__name__)
This behavior can be preferable if you have classes with the same name defined in separate modules.
The sample code provided above was tested in Python 2.7.5.
In Python 2,
type(instance).__name__ != instance.__class__.__name__
# if class A is defined like
class A():
...
type(instance) == instance.__class__
# if class A is defined like
class A(object):
...
Example:
>>> class aclass(object):
... pass
...
>>> a = aclass()
>>> type(a)
<class '__main__.aclass'>
>>> a.__class__
<class '__main__.aclass'>
>>>
>>> type(a).__name__
'aclass'
>>>
>>> a.__class__.__name__
'aclass'
>>>
>>> class bclass():
... pass
...
>>> b = bclass()
>>>
>>> type(b)
<type 'instance'>
>>> b.__class__
<class __main__.bclass at 0xb765047c>
>>> type(b).__name__
'instance'
>>>
>>> b.__class__.__name__
'bclass'
>>>
Alternatively you can use the classmethod decorator:
class A:
#classmethod
def get_classname(cls):
return cls.__name__
def use_classname(self):
return self.get_classname()
Usage:
>>> A.get_classname()
'A'
>>> a = A()
>>> a.get_classname()
'A'
>>> a.use_classname()
'A'
Good question.
Here's a simple example based on GHZ's which might help someone:
>>> class person(object):
def init(self,name):
self.name=name
def info(self)
print "My name is {0}, I am a {1}".format(self.name,self.__class__.__name__)
>>> bob = person(name='Robert')
>>> bob.info()
My name is Robert, I am a person
Apart from grabbing the special __name__ attribute, you might find yourself in need of the qualified name for a given class/function. This is done by grabbing the types __qualname__.
In most cases, these will be exactly the same, but, when dealing with nested classes/methods these differ in the output you get. For example:
class Spam:
def meth(self):
pass
class Bar:
pass
>>> s = Spam()
>>> type(s).__name__
'Spam'
>>> type(s).__qualname__
'Spam'
>>> type(s).Bar.__name__ # type not needed here
'Bar'
>>> type(s).Bar.__qualname__ # type not needed here
'Spam.Bar'
>>> type(s).meth.__name__
'meth'
>>> type(s).meth.__qualname__
'Spam.meth'
Since introspection is what you're after, this is always you might want to consider.
You can simply use __qualname__ which stands for qualified name of a function or class
Example:
>>> class C:
... class D:
... def meth(self):
... pass
...
>>> C.__qualname__
'C'
>>> C.D.__qualname__
'C.D'
>>> C.D.meth.__qualname__
'C.D.meth'
documentation link qualname
To get instance classname:
type(instance).__name__
or
instance.__class__.__name__
both are the same
You can first use type and then str to extract class name from it.
class foo:pass;
bar:foo=foo();
print(str(type(bar))[8:-2][len(str(type(bar).__module__))+1:]);
Result
foo
If you're looking to solve this for a list (or iterable collection) of objects, here's how I would solve:
from operator import attrgetter
# Will use a few data types to show a point
my_list = [1, "2", 3.0, [4], object(), type, None]
# I specifically want to create a generator
my_class_names = list(map(attrgetter("__name__"), map(type, my_list))))
# Result:
['int', 'str', 'float', 'list', 'object', 'type', 'NoneType']
# Alternatively, use a lambda
my_class_names = list(map(lambda x: type(x).__name__, my_list))

Python dictionary from an object's fields

Do you know if there is a built-in function to build a dictionary from an arbitrary object? I'd like to do something like this:
>>> class Foo:
... bar = 'hello'
... baz = 'world'
...
>>> f = Foo()
>>> props(f)
{ 'bar' : 'hello', 'baz' : 'world' }
NOTE: It should not include methods. Only fields.
Note that best practice in Python 2.7 is to use new-style classes (not needed with Python 3), i.e.
class Foo(object):
...
Also, there's a difference between an 'object' and a 'class'. To build a dictionary from an arbitrary object, it's sufficient to use __dict__. Usually, you'll declare your methods at class level and your attributes at instance level, so __dict__ should be fine. For example:
>>> class A(object):
... def __init__(self):
... self.b = 1
... self.c = 2
... def do_nothing(self):
... pass
...
>>> a = A()
>>> a.__dict__
{'c': 2, 'b': 1}
A better approach (suggested by robert in comments) is the builtin vars function:
>>> vars(a)
{'c': 2, 'b': 1}
Alternatively, depending on what you want to do, it might be nice to inherit from dict. Then your class is already a dictionary, and if you want you can override getattr and/or setattr to call through and set the dict. For example:
class Foo(dict):
def __init__(self):
pass
def __getattr__(self, attr):
return self[attr]
# etc...
Instead of x.__dict__, it's actually more pythonic to use vars(x).
The dir builtin will give you all the object's attributes, including special methods like __str__, __dict__ and a whole bunch of others which you probably don't want. But you can do something like:
>>> class Foo(object):
... bar = 'hello'
... baz = 'world'
...
>>> f = Foo()
>>> [name for name in dir(f) if not name.startswith('__')]
[ 'bar', 'baz' ]
>>> dict((name, getattr(f, name)) for name in dir(f) if not name.startswith('__'))
{ 'bar': 'hello', 'baz': 'world' }
So can extend this to only return data attributes and not methods, by defining your props function like this:
import inspect
def props(obj):
pr = {}
for name in dir(obj):
value = getattr(obj, name)
if not name.startswith('__') and not inspect.ismethod(value):
pr[name] = value
return pr
I've settled with a combination of both answers:
dict((key, value) for key, value in f.__dict__.iteritems()
if not callable(value) and not key.startswith('__'))
I thought I'd take some time to show you how you can translate an object to dict via dict(obj).
class A(object):
d = '4'
e = '5'
f = '6'
def __init__(self):
self.a = '1'
self.b = '2'
self.c = '3'
def __iter__(self):
# first start by grabbing the Class items
iters = dict((x,y) for x,y in A.__dict__.items() if x[:2] != '__')
# then update the class items with the instance items
iters.update(self.__dict__)
# now 'yield' through the items
for x,y in iters.items():
yield x,y
a = A()
print(dict(a))
# prints "{'a': '1', 'c': '3', 'b': '2', 'e': '5', 'd': '4', 'f': '6'}"
The key section of this code is the __iter__ function.
As the comments explain, the first thing we do is grab the Class items and prevent anything that starts with '__'.
Once you've created that dict, then you can use the update dict function and pass in the instance __dict__.
These will give you a complete class+instance dictionary of members. Now all that's left is to iterate over them and yield the returns.
Also, if you plan on using this a lot, you can create an #iterable class decorator.
def iterable(cls):
def iterfn(self):
iters = dict((x,y) for x,y in cls.__dict__.items() if x[:2] != '__')
iters.update(self.__dict__)
for x,y in iters.items():
yield x,y
cls.__iter__ = iterfn
return cls
#iterable
class B(object):
d = 'd'
e = 'e'
f = 'f'
def __init__(self):
self.a = 'a'
self.b = 'b'
self.c = 'c'
b = B()
print(dict(b))
A downside of using __dict__ is that it is shallow; it won't convert any subclasses to dictionaries.
If you're using Python3.5 or higher, you can use jsons:
>>> import jsons
>>> jsons.dump(f)
{'bar': 'hello', 'baz': 'world'}
To build a dictionary from an arbitrary object, it's sufficient to use __dict__.
This misses attributes that the object inherits from its class. For example,
class c(object):
x = 3
a = c()
hasattr(a, 'x') is true, but 'x' does not appear in a.__dict__
Python3.x
return dict((key, value) for key, value in f.__dict__.items() if not callable(value) and not key.startswith('__'))
Late answer but provided for completeness and the benefit of googlers:
def props(x):
return dict((key, getattr(x, key)) for key in dir(x) if key not in dir(x.__class__))
This will not show methods defined in the class, but it will still show fields including those assigned to lambdas or those which start with a double underscore.
vars() is great, but doesn't work for nested objects of objects
Convert nested object of objects to dict:
def to_dict(self):
return json.loads(json.dumps(self, default=lambda o: o.__dict__))
I think the easiest way is to create a getitem attribute for the class. If you need to write to the object, you can create a custom setattr . Here is an example for getitem:
class A(object):
def __init__(self):
self.b = 1
self.c = 2
def __getitem__(self, item):
return self.__dict__[item]
# Usage:
a = A()
a.__getitem__('b') # Outputs 1
a.__dict__ # Outputs {'c': 2, 'b': 1}
vars(a) # Outputs {'c': 2, 'b': 1}
dict generates the objects attributes into a dictionary and the dictionary object can be used to get the item you need.
In 2021, and for nested objects/dicts/json use pydantic BaseModel - will convert nested dicts and nested json objects to python objects and JSON and vice versa:
https://pydantic-docs.helpmanual.io/usage/models/
>>> class Foo(BaseModel):
... count: int
... size: float = None
...
>>>
>>> class Bar(BaseModel):
... apple = 'x'
... banana = 'y'
...
>>>
>>> class Spam(BaseModel):
... foo: Foo
... bars: List[Bar]
...
>>>
>>> m = Spam(foo={'count': 4}, bars=[{'apple': 'x1'}, {'apple': 'x2'}])
Object to dict
>>> print(m.dict())
{'foo': {'count': 4, 'size': None}, 'bars': [{'apple': 'x1', 'banana': 'y'}, {'apple': 'x2', 'banana': 'y'}]}
Object to JSON
>>> print(m.json())
{"foo": {"count": 4, "size": null}, "bars": [{"apple": "x1", "banana": "y"}, {"apple": "x2", "banana": "y"}]}
Dict to object
>>> spam = Spam.parse_obj({'foo': {'count': 4, 'size': None}, 'bars': [{'apple': 'x1', 'banana': 'y'}, {'apple': 'x2', 'banana': 'y2'}]})
>>> spam
Spam(foo=Foo(count=4, size=None), bars=[Bar(apple='x1', banana='y'), Bar(apple='x2', banana='y2')])
JSON to object
>>> spam = Spam.parse_raw('{"foo": {"count": 4, "size": null}, "bars": [{"apple": "x1", "banana": "y"}, {"apple": "x2", "banana": "y"}]}')
>>> spam
Spam(foo=Foo(count=4, size=None), bars=[Bar(apple='x1', banana='y'), Bar(apple='x2', banana='y')])
Dataclass(from Python 3.7) is another option which can be used for converting class properties to dict. asdict can be used along with dataclass objects
for the conversion.
Example:
#dataclass
class Point:
x: int
y: int
p = Point(10, 20)
asdict(p) # it returns {'x': 10, 'y': 20}
As mentioned in one of the comments above, vars currently isn't universal in that it doesn't work for objects with __slots__ instead of a normal __dict__. Moreover, some objecs (e.g., builtins like str or int) have neither a __dict__ nor __slots__.
For now, a more versatile solution could be this:
def instance_attributes(obj: Any) -> Dict[str, Any]:
"""Get a name-to-value dictionary of instance attributes of an arbitrary object."""
try:
return vars(obj)
except TypeError:
pass
# object doesn't have __dict__, try with __slots__
try:
slots = obj.__slots__
except AttributeError:
# doesn't have __dict__ nor __slots__, probably a builtin like str or int
return {}
# collect all slots attributes (some might not be present)
attrs = {}
for name in slots:
try:
attrs[name] = getattr(obj, name)
except AttributeError:
continue
return attrs
Example:
class Foo:
class_var = "spam"
class Bar:
class_var = "eggs"
__slots__ = ["a", "b"]
>>> foo = Foo()
>>> foo.a = 1
>>> foo.b = 2
>>> instance_attributes(foo)
{'a': 1, 'b': 2}
>>> bar = Bar()
>>> bar.a = 3
>>> instance_attributes(bar)
{'a': 3}
>>> instance_attributes("baz")
{}
Rant:
It's a pity that this isn't built into vars already. Many builtins in Python promise to be "the" solution to a problem but then there's always several special cases that aren't handled... And one just ends up having to write the code manually in any case.
If you want to list part of your attributes, override __dict__:
def __dict__(self):
d = {
'attr_1' : self.attr_1,
...
}
return d
# Call __dict__
d = instance.__dict__()
This helps a lot if your instance get some large block data and you want to push d to Redis like message queue.
PYTHON 3:
class DateTimeDecoder(json.JSONDecoder):
def __init__(self, *args, **kargs):
JSONDecoder.__init__(self, object_hook=self.dict_to_object,
*args, **kargs)
def dict_to_object(self, d):
if '__type__' not in d:
return d
type = d.pop('__type__')
try:
dateobj = datetime(**d)
return dateobj
except:
d['__type__'] = type
return d
def json_default_format(value):
try:
if isinstance(value, datetime):
return {
'__type__': 'datetime',
'year': value.year,
'month': value.month,
'day': value.day,
'hour': value.hour,
'minute': value.minute,
'second': value.second,
'microsecond': value.microsecond,
}
if isinstance(value, decimal.Decimal):
return float(value)
if isinstance(value, Enum):
return value.name
else:
return vars(value)
except Exception as e:
raise ValueError
Now you can use above code inside your own class :
class Foo():
def toJSON(self):
return json.loads(
json.dumps(self, sort_keys=True, indent=4, separators=(',', ': '), default=json_default_format), cls=DateTimeDecoder)
Foo().toJSON()
Try:
from pprint import pformat
a_dict = eval(pformat(an_obj))
Python 3.7+ in 2023
You can add the dataclass decorator to your class and define a custom JSON serializer, then json.dumps will work (and you can extend it to work with non-serializable attributes by providing a custom encoder to cls).
f=Foo()
json.dumps(f, cls=CustomJSONEncoder)
{"bar": "hello", "baz": "world", "modified": "2023-02-08T11:49:15.675837"}
A custom JSON serializer can be easily modified to make it compatible with any type that isn't natively JSON serializable.
from datetime import datetime
import dataclasses
import json
#dataclasses.dataclass # <<-- add this decorator
class Foo():
"""An example dataclass."""
bar: str = "hello"
baz: str = "world"
modified: datetime = Column(DateTime(timezone=True), default=datetime.utcnow)
class CustomJSONEncoder(json.JSONEncoder): # <<-- Add this custom encoder
"""Custom JSON encoder for the DB class."""
def default(self, o):
if dataclasses.is_dataclass(o): # this serializes anything dataclass can handle
return dataclasses.asdict(o)
if isinstance(o, datetime): # this adds support for datetime
return o.isoformat()
return super().default(o)
To further extend it for any non-serializable type, add another if statement to the custom encoder class that returns something serializable (e.g. str).

Categories