Possible duplicates:
Is there a way to create subclasses on-the-fly?
Dynamically creating classes - Python
I would like to create a subclass where the only difference is some class variable, but I would like everything else to stay the same. I need to do this dynamically, because I only know the class variable value at run time.
Here is some example code so far. I would like FooBase.foo_var to be "default" but FooBar.foo_var to be "bar." No attempt so far has been successful.
class FooBase(object):
foo_var = "default"
def __init__(self, name="anon"):
self.name = name
def speak(self):
print self.name, "reporting for duty"
print "my foovar is '" + FooBase.foo_var + "'"
if __name__ == "__main__":
#FooBase.foo_var = "foo"
f = FooBase()
f.speak()
foobarname = "bar"
#FooBar = type("FooBar", (FooBase,), {'foo_var': "bar"})
class FooBar(FooBase): pass
FooBar.foo_var = "bar"
fb = FooBar()
fb.speak()
Many thanks
EDIT so I obviously have a problem with this line:
print "my foovar is '" + FooBase.foo_var + "'"
The accepted answer has self.foo_var in the code. That's what I should be doing. I feel ridiculous now.
What about this:
def make_class(value):
class Foo(object):
foo_var = value
def speak(self):
print self.foo_var
return Foo
FooBar = make_class("bar")
FooQux = make_class("qux")
FooBar().speak()
FooQux().speak()
That said, can't you make the value of foo_var be a instance variable of your class? So that the same class instantiated with different input behaves in different ways, instead of creating a different class for each of those different behaviours.
Related
I have the following code, while it isn't my actual code it shows the problem I'm having:
class SubObject:
value = None
class Object:
subObject = SubObject()
object0 = Object()
object0.subObject.value = 'hello'
object1 = Object()
object1.subObject.value = 'world'
print object0.subObject.value + ' ' + object1.subObject.value
I have a class SubObject that is used in another class Object but when I create two Object variables they share the same instance of SubObject. This has been causing me plenty of frustration and my actual code really needs the class-in-class, so refactoring into one massive class isn't really what I want to do.
Running the above code in python 2 prints world world
Initialize the data members of the classes using proper constructors. This would be one way to solve this:
class SubObject:
def __init__ (self):
self.value = None
class Object:
def __init__ (self):
self.subObject = SubObject()
object0 = Object()
object0.subObject.value = 'hello'
object1 = Object()
object1.subObject.value = 'world'
print object0.subObject.value + ' ' + object1.subObject.value
The output for this program is:
hello world
I have an enum like this
#enum.unique
class TransactionTypes(enum.IntEnum):
authorisation = 1
balance_adjustment = 2
chargeback = 3
auth_reversal = 4
Now i am assigning a variable with this enum like this
a = TransactionTypes
I want to check for the type of 'a' and do something if its an enum and something else, if its not an enum
I tried something like this
if type(a) == enum:
print "do enum related stuff"
else:
print "do something else"
The problem is it is not working fine.
Now i am assigning a variable with this enum like this
a = TransactionTypes
I hope you aren't, because what you just assigned to a is the entire enumeration, not one of its members (such as TransactionTypes.chargeback) If that is really what you wanted to do, then the correct test would be:
if issubclass(a, enum.Enum)
However, if you actually meant something like:
a = TransactionTypes.authorisation
then the test you need is:
# for any Enum member
if isinstance(a, Enum):
or
# for a TransactionTypes Enum
if isinstance(a, TransactionTypes):
reliable solution:
from enum import IntEnum
from collections import Iterable
def is_IntEnum(obj):
try:
return isinstance(obj, Iterable) and isinstance (next(iter(obj)), IntEnum)
except:
return False # Handle StopIteration, if obj has no elements
I thought I`ve got a ugly way. eg:
print(o.__class__.__class__)
Output:
<enum.EnumMeta>
as mentioned use isinstance method to check weather an instance is of enum.Enum type or not.
A small working code for demonstration of its usage:
import enum
class STATUS(enum.Enum):
FINISHED = enum.auto()
DELETED = enum.auto()
CANCELLED = enum.auto()
PENDING = enum.auto()
if __name__ == "__main__":
instance = STATUS.CANCELLED
if isinstance(instance, enum.Enum):
print('name : ', instance.name, ' value : ', instance.value)
else:
print(str(instance))
Output:
name : CANCELLED value : 3
There are already good answers here but in case of it might be useful for some people out there
I wanted to stretch the question a little further and created a simple example
to propose a humble solution to help caller function who does maybe little knowledge about Enum
solve problem of sending arguments to functions that take only Enum
as a parameter by proposing a converter just below the file that Enum was created.
from enum import Enum
from typing import Union
class Polygon(Enum):
triangle: 3
quadrilateral: 4
pentagon: 5
hexagon: 6
heptagon: 7
octagon: 8
nonagon: 9
decagon: 10
def display(polygon: Polygon):
print(f"{polygon.name} : {polygon.value} ")
def do_something_with_polygon(polygon: Polygon):
"""This one is not flexible cause it only accepts a Polygon Enum it does not convert"""
""" if parameter is really a Polygon Enum we are ready to do stuff or We get error """
display(polygon)
def do_something_with_polygon_more_flexible(maybe_polygon_maybe_not: Union[Polygon, int, str]):
""" it will be more convenient function by taking extra parameters and converting"""
if isinstance(maybe_polygon_maybe_not, Enum):
real_polygon = maybe_polygon_maybe_not
else:
real_polygon = get_enum_with_value(int(maybe_polygon_maybe_not), Polygon, Polygon.quadrilateral)
""" now we are ready to do stuff """
display(real_polygon)
def get_enum_with_value(key: int, enum_: any, default_value: Enum):
""" this function will convert int value to Enum that corresponds checking parameter key """
# create a dict with all values and name of Enum
dict_temp = {x.value: x for x in
enum_} # { 3 : Polygon.triangle , 4 :Polygon.quadrilateral , 5 : Polygon.pentagon , ... }
# if key exists for example 6 or '6' that comes to do_something_with_polygon_more_flexible
# returns Polygon.hexagon
enum_value = dict_temp.get(key, None)
# if key does not exist we get None
if not enum_value:
... # if key does not exist we return default value (Polygon.quadrilateral)
enum_value = default_value # Polygon.quadrilateral
return enum_value
I'm getting this error:
unbound method hello() must be called with A instance as first argument(got nothing instead)
import B
class A():
#staticmethod
def newHello():
A.oldHello() # Here the error
print ' world'
def inject(self):
A.oldHello = B.hello
B.hello = A.newHello
A().inject()
B.hello()
B.py contain only a function "hello" that print "hello"
def hello():
print 'hello'
Thanks in advance
A.oldhello() is not static. So in B's hello function is referencing A's nonstatic oldhello statically. A does in fact need an instance. I'm not too good with the decorators and how they work but maybe try declaring oldhello in the class before the function and calling it #staticmethod. I don't know if the staticness carries over if you override the method.
Try this:
class B():
def hello(self):
print "hello"
class A():
#staticmethod
def newHello(self):
A.oldHello(self) # Here the error
print ' world'
def inject(self):
A.oldHello = B.hello
B.hello = A.newHello
A().inject()
B().hello()
I have a custom class called Values that is a wrapper of arrays. For a given object vFoo of class Values, which contains an array of objects of class Foo, the var format -T vFoocommand returns the following structure:
(MyNameSpace::Values) vFoo = {
(void *) p = 0x0000000100204378
(size_t) n = 2
(MyNameSpace::ValueType) type = FOO
}
where vFoo.p is a pointer to the array<Foo> that contains 2 elements. I can access the array elements with the following command in the lldb prompt:
expression ((MyNameSpace::Foo*)vFoo.p)[0]
which returns
(MyNameSpace::Foo) $0 = "foo"
according to my summary provider.
I would like to write a synthetic child provider that returns something like:
(MyNameSpace::Values) vFoo = {
(MyNameSpace::Foo) vFoo.p[0] = "foo"
(MyNameSpace::Foo) vFoo.p[1] = "bar"
}
Unfortunately, I have no idea how to do that. I read the lldb data formatters page and try to follow the structure given at the end of the page. I have also had a look at the bitfield and libcxx examples, but I can't find my way to the solution. Any help would be deeply appreciated!
Many thanks in advance
You need to get the internal representation of the type Foo. You can get this from the SBModule using self.valobj.GetFrame().GetModule().FindFirstType("Foo"). Something like this will work with some poking around.
class Values_SynthProvider:
def __init__(self, valobj, dict):
self.valobj = valobj
self.num_elements = None
def update(self):
self.num_elements = self.valobj.GetChildMemberWithName('n').GetValueAsUnsigned(0)
def num_children(self):
return self.num_elements
def get_child_at_index(self,index):
# Here you could switch on the value of Values::type to get the right type name to search for
foo_type = self.valobj.GetFrame().GetModule().FindFirstType("Foo")
return self.valobj.GetChildMemberWithName('p').Cast(foo_type.GetPointerType()).GetChildAtIndex(index,0,True)
def get_child_index(self,name):
return int(name.lstrip('[').rstrip(']'))
I have several classes. The desired behavior on an instance creation is that an instance is assigned an ID. For simplicity, let us assume that IDs should start at 0 and increase by 1 with every instance creation. For each of these several classes, the IDs should be incremented independently.
I know how to do this in C++. I have actually also done that in Python, but I do not like it as much as the C++ solution, and I am wondering whether it is due to my limited knowledge of Python (little more than 6 weeks), or whether there is a better, more Pythonic way.
In C++, I have implemented this both using inheritance, and using composition. Both implementations use the Curiously Recurring Template Pattern (CRPT) idiom. I slightly prefer the inheritance way:
#include <iostream>
template<class T>
class Countable{
static int counter;
public:
int id;
Countable() : id(counter++){}
};
template<class T>
int Countable<T>::counter = 0;
class Counted : public Countable<Counted>{};
class AnotherCounted: public Countable<AnotherCounted>{};
int main(){
Counted element0;
Counted element1;
Counted element2;
AnotherCounted another_element0;
std::cout << "This should be 2, and actually is: " << element2.id << std::endl;
std::cout << "This should be 0, and actually is: " << another_element0.id << std::endl;
}
to the composion way:
#include <iostream>
template<class T>
class Countable{
static int counter;
public:
int id;
Countable() : id(counter++){}
};
template<class T>
int Countable<T>::counter = 0;
class Counted{
public:
Countable<Counted> counterObject;
};
class AnotherCounted{
public:
Countable<AnotherCounted> counterObject;
};
int main(){
Counted element0;
Counted element1;
Counted element2;
AnotherCounted another_element0;
std::cout << "This should be 2, and actually is: " << element2.counterObject.id << std::endl;
std::cout << "This should be 0, and actually is: " << another_element0.counterObject.id << std::endl;
}
Now, in python, there are no templates which would give me different counters for each class. Thus, I wrapped the countable class to a function, and obtained the following implementation: (inheritance way)
def Countable():
class _Countable:
counter = 0
def __init__(self):
self.id = _Countable.counter
_Countable.counter += 1
return _Countable
class Counted ( Countable() ) :
pass
class AnotherCounted( Countable() ):
pass
element0 = Counted()
element1 = Counted()
element2 = Counted()
another_element0 = AnotherCounted()
print "This should be 2, and actually is:", element2.id
print "This should be 0, and actually is:", another_element0.id
and the composition way:
def Countable():
class _Countable:
counter = 0
def __init__(self):
self.id = _Countable.counter
_Countable.counter += 1
return _Countable
class Counted ( Countable() ) :
counterClass = Countable()
def __init__(self):
self.counterObject = Counted.counterClass()
class AnotherCounted( Countable() ):
counterClass = Countable()
def __init__(self):
self.counterObject = self.counterClass()
element0 = Counted()
element1 = Counted()
element2 = Counted()
another_element0 = AnotherCounted()
print "This should be 2, and actually is:", element2.counterObject.id
print "This should be 0, and actually is:", another_element0.counterObject.id
What troubles me is this. In C++, I have a good idea what I am doing, and e.g. I see no problems even if my classes actually inherit multiply (not just from Countable<> templated class) - everything is very simple.
Now, in Python, I see the following issues:
1) when I use composition, I instantiate the counting class like that:
counterClass = Countable()
I have to do this for every class, and this is possibly error-prone.
2) when I use inheritance, I will bump to further troubles when I will want to ihnerit multiply. Note that above, I have not defined the __init__'s of Counted nor of AnotherCounted, but if I inherited multiply I would have to call base class constructors explicitly, or using super(). I do not like this (yet?) I could also use metaclasses, but my knowledge is limited there and it seems that it adds complexity rather than simplicity.
In conclusion, I think that composition way is probably better for Python implementation, despite the issue with having to explicitly define the counterClass class attribute with Countable().
I would appreciate your opinion on validity of my conclusion.
I would also appreciate hints on better solutions than mine.
Thank you.
I would use __new__, that way you don't have to remember doing anything in __init__:
class Countable(object):
counter = 0
def __new__(cls, *a, **kw):
instance = super(Countable, cls).__new__(cls, *a, **kw)
instance.id = cls.counter + 1
cls.counter = instance.id
return instance
class A(Countable):
pass
class B(Countable):
pass
print A().id, A().id # 1 2
print B().id # 1
I might use a simple class decorator ...
import itertools
def countable(cls):
cls.counter = itertools.count()
return cls
#countable
class Foo(object):
def __init__(self):
self.ID = next(self.__class__.counter)
#countable
class Bar(Foo):
pass
f = Foo()
print f.ID
b = Bar()
print b.ID
If you really want to do this the "fancy" way, you could use a metaclass:
import itertools
class Countable(type):
def __new__(cls,name,bases,dct):
dct['counter'] = itertools.count()
return super(Countable,cls).__new__(cls,name,bases,dct)
class Foo(object):
__metaclass__ = Countable
def __init__(self):
self.ID = next(self.__class__.counter)
class Bar(Foo):
pass
f = Foo()
print f.ID
b = Bar()
print b.ID