Instantiate class by reference - python

I would like to create a dictionary which based on a string keyword returns a subclass of Foo which I can later instantiate. Is this possible or is it an incorrect approach to the problem?
Pseudo code:
subclasses_of_foo = {"foo1": Foo1, "foo2": Foo2}
subclass_of_foo = subclasses_of_foo["foo1"]
instance = subclass_of_foo()

Sure, you can do that. Give it a go.

Your approach is entirely correct and works. Classes are just objects, just like everything else in Python. They can be stored as values in a dictionary.
Demo:
>>> class Foo:
... pass
...
>>> class Bar:
... pass
...
>>> classmap = {'foo': Foo, 'bar': Bar}
>>> classmap['foo']
<class __main__.Foo at 0x107eee1f0>
>>> classmap['foo']()
<__main__.Foo instance at 0x107eefcb0>
Note that duck typing is something else entirely; it is the practice of treating any object as the correct type provided it implements the attributes and methods you expected (if it walks like a duck, it is a duck).

Related

how to access object attribute that having name with space

I used setattr method to set column names from an Excel file as attribute of object. However, these names include spaces like "Vendor name". How can I access the attribute like this?
for k in self.df.columns.values.tolist():
setattr(self,k,self.df[k])
With getattr, of course:
>>> class MyClass: pass
...
>>> my_object = MyClass()
>>> setattr(my_object, 'spaces are considered harmful', 42)
>>> getattr(my_object, 'spaces are considered harmful')
42
Or, you can always access the namespace of a custom class (where you haven't defined __slots__) by using the namespace directly:
>>> vars(my_object) is my_object.__dict__
True
>>> vars(my_object)
{'spaces are considered harmful': 42}
>>> my_object.__dict__
{'spaces are considered harmful': 42}
>>> vars(my_object)['spaces are considered harmful']
42
>>> my_object.__dict__['spaces are considered harmful']
42
Although really, instead of a custom class, it sounds like you want some container that is a sort of mapping from strings to other objects.

Python simple naked objects

What's the easiest way to create a naked object that I can assign attributes to?
The specific use case is: I'm doing various operations on a Django object instance, but sometimes the instance is None (there is on instance). In this case I'd like to create the simplest possible fake object such that I can assign values to its attributes (eg. myobject.foo = 'bar').
Basically I'm looking for the Python equivalent of this piece of Javascript:
myobject = {}
myobject.foo = 'bar'
I know I can use a mock object/library for this, but I'm hoping for a very simple solution (as simple as the Javascript above). Is there a way to create a naked object instance? Something like:
myobject = object()
myobject.foo = 'bar'
You need to create a simple class first:
class Foo(object):
pass
myobject = Foo()
myobject.foo = 'bar'
You can make it a one-liner like this:
myobject = type("Foo", (object,), {})()
myobject.foo = 'bar'
The call to type functions identically to the previous class statement.
If you want to be really minimal...
myobject = type("", (), {})()
The key is that the built-in types (such as list and object) don't support user-defined attributes, so you need to create a type using either a class statement or a call to the 3-parameter version of type.
If you're using Python >= 3.3 you could always use SimpleNamespace; which is included in the Python types module.
SimpleNamespace is great because you also get a repr and equivalency testing for free; both of which might come in handy even for a minimalist object.
Translating the JavaScript in the OP’s question would look like:
from types import SimpleNamespace
myobject = SimpleNamespace() # myobject = {}
myobject.foo = 'bar'
You can also use keyword arguments when instantiating SimpleNamespace. These arguments will become attributes on the instantiated SimpleNamespace:
p = SimpleNamespace(name='gary')
p.age = 32
p # => namespace(age=32, name='gary')
So a quick and easy way to turn a dictionary into a SimpleNamespace object —provided the dictionary keys are proper identifiers— is as simple as:
d = {
'name': 'gary',
'age': 33 # had a birthday.
}
p = SimpleNamespace(**d)
Python >= 3.7 has dataclasses which are basically “mutable named tuples”. This could be something you may want to use if you have a lot of data objects.
Use the Bunch module:
sudo pip install bunch
A bunch is a dictionary that allows to access its content via the dict.key syntax.
And then like that:
from bunch import Bunch
b = Bunch()
b.foo = "Bar"
b["foo2"] = "Bar2"
print b
>> Bunch(foo='Bar', foo2='Bar2')
b["foo"] = "Baz"
print b
>> Bunch(foo='Baz', foo2='Bar2')
I'm coming here very late, but I'm surprised nobody has mentioned namedtuples, which accomplish this kind of thing:
Foo = namedtuple('Foo', ['x'])
f = Foo(x='myattribute')
f.x
For Python 3,
class Obj: pass
o = Obj()
o.name = 'gary'
o.age = 32
o
# <__main__.Obj at 0x17235ca65c0>
o.__dict__
# {'name': 'gary', 'age': 32}
class NakedObject(object):
pass
myobject = NakedObject()
myobject.foo = 'bar'
Functions can have attributes in Python 3. Compared to a naked class, you can save one whole line of code.
naked = lambda: None
naked.foo = 'bar'
You would need to subclass object first like this...
class Myobject(object):
pass
myobject1 = Myobject()
myobject1.foo = 'bar'
Perhaps you are looking for something like this:
myobject={}
myobject['foo']='bar'
then it can be called like:
print myobject['foo']
or you could use a class object for this:
class holder(object):
pass
then you can use something like this:
hold=holder()
hold.myobject='bar'
print hold.myobject
You should probably just use a dict, as per #PsychicOak's answer.
However, if you really want an object you can manipulate, try:
class FooClass(object): pass
You can then assign attributes on FooClass itself, or on instances, as you wish.
I usually prefer to create a null object for my class:
class User(Model):
username = CharField()
password = CharField()
NONE_USER = User(username='', password='')
Then I use it where I would use your naked object.
In some cases extending a dict can help you
like:
class SpecificModelData(dict):
pass
...
class Payload(dict):
... enter code here
why a dict? it works nicely together with serializers.
Why new class? - it gives you a name and a new type

Recursively walking a Python inheritance tree at run-time

I'm writing some serialization/deserialization code in Python that will read/write an inheritance hierarchy from some JSON. The exact composition will not be known until the request is sent in.
So, I deem the elegant solution to recursively introspect the Python class hierarchy to be emitted and then, on the way back up through the tree, install the correct values in a Python basic type.
E.g.,
A
|
|\
| \
B C
If I call my "introspect" routine on B, it should return a dict that contains a mapping from all of A's variables to their values, as well as B's variables and their values.
As it now stands, I can look through B.__slots__ or B.__dict__, but I only can pull out B's variable names from there.
How do I get the __slots__/__dict__ of A, given only B? (or C).
I know that python doesn't directly support casting like C++ & its descendants do-
You might try using the type.mro() method to find the method resolution order.
class A(object):
pass
class B(A):
pass
class C(A):
pass
a = A()
b = B()
c = C()
>>> type.mro(type(b))
[<class '__main__.B'>, <class '__main__.A'>, <type 'object'>]
>>> type.mro(type(c))
[<class '__main__.C'>, <class '__main__.A'>, <type 'object'>]
or
>>> type(b).mro()
Edit: I was thinking you wanted to do something like this...
>>> A = type("A", (object,), {'a':'A var'}) # create class A
>>> B = type("B", (A,), {'b':'B var'}) # create class B
>>> myvar = B()
def getvars(obj):
''' return dict where key/value is attribute-name/class-name '''
retval = dict()
for i in type(obj).mro():
for k in i.__dict__:
if not k.startswith('_'):
retval[k] = i.__name__
return retval
>>> getvars(myvar)
{'a': 'A', 'b': 'B'}
>>> for i in getvars(myvar):
print getattr(myvar, i) # or use setattr to modify the attribute value
A Var
B Var
Perhaps you could clarify what you are looking for a bit further?
At the moment your description doesn't describe Python at all. Let's assume that in your example A, B and C are the names of the classes:
class A(object) :
... def __init__(self) :
... self.x = 1
class B(A) :
... def __init__(self) :
... A.__init__(self)
... self.y = 1
Then a runtime instance could be created as:
b = B()
If you look at the dictionary of the runtime object then it has no distinction between its own variables and variables belonging to its superclass. So for example :
dir(b)
[ ... snip lots of double-underscores ... , 'x', 'y']
So the direct answer to your question is that it works like that already, but I suspect that is not very helpful to you. What does not show up is methods as they are entries in the namespace of the class, while variables are in the namespace of the object. If you want to find methods in superclasses then use the mro() call as described in the earlier reply and then look through the namespaces of the classes in the list.
While I was looking around for simpler ways to do JSON serialisation I found some interesting things in the pickle module. One suggestion is that you might want to pickle / unpickle objects rather than write your own to traverse the hieracrchy. The pickle output is an ASCII stream and it may be easier for you to convert that back and forth to JSON. There are some starting points in PEP 307.
The other suggestion is to take a look at the __reduce__ method, try it on the objects that you want to serialise as it may be what you are looking for.
If you only need a tree (not diamond shaped inheritance), there is a simple way to do it. Represent the tree by a nested list of branch [object, [children]] and leaves [object, [[]]].
Then, by defining the recursive function:
def classTree(cls): # return all subclasses in form of a tree (nested list)
return [cls, [[b for c in cls.__subclasses__() for b in classTree(c)]]]
You can get the inheritance tree:
class A():
pass
class B(A):
pass
class C(B):
pass
class D(C):
pass
class E(B):
pass
>>> classTree(A)
[<class 'A'>, [[<class 'B'>, [[<class 'C'>, [[<class 'D'>, [[]]]], <class 'E'>, [[]]]]]]]
Which is easy to serialize since it's only a list. If you want only the names, replace cls by cls.__name__.
For deserialisation, you have to get your class back from text. Please provide details in your question if you want more help for this.

Difference between type(obj) and obj.__class__

What is the difference between type(obj) and obj.__class__? Is there ever a possibility of type(obj) is not obj.__class__?
I want to write a function that works generically on the supplied objects, using a default value of 1 in the same type as another parameter. Which variation, #1 or #2 below, is going to do the right thing?
def f(a, b=None):
if b is None:
b = type(a)(1) # #1
b = a.__class__(1) # #2
This is an old question, but none of the answers seems to mention that. in the general case, it IS possible for a new-style class to have different values for type(instance) and instance.__class__:
class ClassA(object):
def display(self):
print("ClassA")
class ClassB(object):
__class__ = ClassA
def display(self):
print("ClassB")
instance = ClassB()
print(type(instance))
print(instance.__class__)
instance.display()
Output:
<class '__main__.ClassB'>
<class '__main__.ClassA'>
ClassB
The reason is that ClassB is overriding the __class__ descriptor, however the internal type field in the object is not changed. type(instance) reads directly from that type field, so it returns the correct value, whereas instance.__class__ refers to the new descriptor replacing the original descriptor provided by Python, which reads the internal type field. Instead of reading that internal type field, it returns a hardcoded value.
Old-style classes are the problem, sigh:
>>> class old: pass
...
>>> x=old()
>>> type(x)
<type 'instance'>
>>> x.__class__
<class __main__.old at 0x6a150>
>>>
Not a problem in Python 3 since all classes are new-style now;-).
In Python 2, a class is new-style only if it inherits from another new-style class (including object and the various built-in types such as dict, list, set, ...) or implicitly or explicitly sets __metaclass__ to type.
type(obj) and type.__class__ do not behave the same for old style classes:
>>> class a(object):
... pass
...
>>> class b(a):
... pass
...
>>> class c:
... pass
...
>>> ai=a()
>>> bi=b()
>>> ci=c()
>>> type(ai) is ai.__class__
True
>>> type(bi) is bi.__class__
True
>>> type(ci) is ci.__class__
False
There's an interesting edge case with proxy objects (that use weak references):
>>> import weakref
>>> class MyClass:
... x = 42
...
>>> obj = MyClass()
>>> obj_proxy = weakref.proxy(obj)
>>> obj_proxy.x # proxies attribute lookup to the referenced object
42
>>> type(obj_proxy) # returns type of the proxy
weakproxy
>>> obj_proxy.__class__ # returns type of the referenced object
__main__.MyClass
>>> del obj # breaks the proxy's weak reference
>>> type(obj_proxy) # still works
weakproxy
>>> obj_proxy.__class__ # fails
ReferenceError: weakly-referenced object no longer exists
FYI - Django does this.
>>> from django.core.files.storage import default_storage
>>> type(default_storage)
django.core.files.storage.DefaultStorage
>>> default_storage.__class__
django.core.files.storage.FileSystemStorage
As someone with finite cognitive capacity who's just trying to figure out what's going in order to get work done... it's frustrating.

How to check whether a variable is a class or not?

I was wondering how to check whether a variable is a class (not an instance!) or not.
I've tried to use the function isinstance(object, class_or_type_or_tuple) to do this, but I don't know what type would a class will have.
For example, in the following code
class Foo: pass
isinstance(Foo, **???**) # i want to make this return True.
I tried to substitute "class" with ???, but I realized that class is a keyword in python.
Even better: use the inspect.isclass function.
>>> import inspect
>>> class X(object):
... pass
...
>>> inspect.isclass(X)
True
>>> x = X()
>>> isinstance(x, X)
True
>>> inspect.isclass(x)
False
>>> class X(object):
... pass
...
>>> type(X)
<type 'type'>
>>> isinstance(X,type)
True
The inspect.isclass is probably the best solution, and it's really easy to see how it's actually implemented
def isclass(obj):
"""Return true if the obj is a class.
Class objects provide these attributes:
__doc__ documentation string
__module__ name of module in which this class was defined"""
return isinstance(obj, (type, types.ClassType))
isinstance(X, type)
Return True if X is class and False if not.
This check is compatible with both Python 2.x and Python 3.x.
import six
isinstance(obj, six.class_types)
This is basically a wrapper function that performs the same check as in andrea_crotti answer.
Example:
>>> import datetime
>>> isinstance(datetime.date, six.class_types)
>>> True
>>> isinstance(datetime.date.min, six.class_types)
>>> False
Benjamin Peterson is correct about the use of inspect.isclass() for this job.
But note that you can test if a Class object is a specific Class, and therefore implicitly a Class, using the built-in function issubclass.
Depending on your use-case this can be more pythonic.
from typing import Type, Any
def isclass(cl: Type[Any]):
try:
return issubclass(cl, cl)
except TypeError:
return False
Can then be used like this:
>>> class X():
... pass
...
>>> isclass(X)
True
>>> isclass(X())
False
class Foo: is called old style class and class X(object): is called new style class.
Check this What is the difference between old style and new style classes in Python? . New style is recommended. Read about "unifying types and classes"
simplest way is to use inspect.isclass as posted in the most-voted answer.
the implementation details could be found at python2 inspect and python3 inspect.
for new-style class: isinstance(object, type)
for old-style class: isinstance(object, types.ClassType)
em, for old-style class, it is using types.ClassType, here is the code from types.py:
class _C:
def _m(self): pass
ClassType = type(_C)
Well, inspect.isclass is not working for me, instead, try this
class foo:
pass
var = foo()
if str(type(var)).split(".")[0] == "<class '__main__":
print("this is a class")
else:
print(str(type(var)).split(".")[0])
So basically, type(var) is <class 'a type'>
Example: <class 'int'
But, when var is a class, it will appear something like <class '__main__.classname'>
So we split the string into <class '__main__ and we compare using if, if the string fit perfectly then it's a class
There is an alternative way to check it:
import inspect
class cls():
print(None)
inspect.isclass(cls)
Reference: https://www.kite.com/python/docs/inspect.isclass
In some cases (depending on your system), a simple test is to see if your variable has a __module__ attribute.
if getattr(my_variable,'__module__', None):
print(my_variable, ".__module__ is ",my_variable.__module__)
else:
print(my_variable,' has no __module__.')
int, float, dict, list, str etc do not have __module__
There are some working solutions here already, but here's another one:
>>> import types
>>> class Dummy: pass
>>> type(Dummy) is types.ClassType
True

Categories