Generating class dynamically from a list of values
Say I got a list of dictionaries like so:
[
dict(name='Person', title='Person class'),
dict(name='Employee', title='Employee class')
]
And I want to create to classes; one named Person with an attribute title set to 'Person class' and another class called Employee with title set to 'Employee class'. The name of the class can be whatever, but the name of the attributes the class will have are known, in this case title.
What I want to end up with is a new list of dynamically created classes;
classes = [Person, Employee]
As if the class had been defined manually:
class Person:
title = 'Person class'
which can be instantiated like so :
>>> x = classes[0]()
>>> print x.title
"Person class"
And as if that wasn't bad enough I'd like to assign a method defined in a different class to the dynamically created classes:
class X:
def sum(self, a, b):
print self
return a+b
>>> x = X()
>>> x.sum(1,2)
__main__.x
3
>>> classes[0开发者_开发知识库].sum = X.sum
>>> classes[0].sum(1,2)
__main__.Person
3
I know the above doesn't work - and perhaps it doesn't even make sense. But can it be done shomehow - assigning a method defined in a class to a different class?
Use built-in function type()
:
>>> d
[{'name': 'Person', 'title': 'Person class'}, {'name': 'Employee', 'title': 'Employee class'}]
>>> types = [type(x['name'], (object,), {'title': x['title']}) for x in d]
>>> types[0]()
<__main__.Person object at 0x800f5fad0>
>>> types[0]().title
'Person class'
Modification for the second question:
>>> class X(object):
... def sum(self, a, b):
... print self
... return a+b
...
>>> types = [type(x['name'], (object,), {'title': x['title'], 'sum': X.__dict__['sum']}) for x in d]
>>> types[0]().sum(1,2)
<__main__.Person object at 0x800f5fad0>
3
Just a note, why X.__dict__['sum']
and not X.sum
: X.sum
returns <unbound method X.sum>
- function that 'knows' that it belongs to X
class. Raw function sum
as it was defined in a class lies in X.__dict__
. You can read more in Unifying types and classes.
But still, make sure that you need this and you fully understand what is doing here.
You can use type
function:
>>> d = [
... dict(name='Person', title='Person class'),
... dict(name='Employee', title='Employee class')
... ]
>>> t = [type(i["name"], (object,), i) for i in d]
>>> t
[<class '__main__.Person'>, <class '__main__.Employee'>]
>>> t[0].title
'Person class'
>>> t[1].title
'Employee class'
There is a wonderful type()
function in Python, which can either return a type of a variable, or create a new type, for example:
Person = type('Person', (object, ), { 'name' : 'Alex',
'last_name' : 'Black' } )
Employee = type('Employee', (Person, ), { 'job' : 'Programmer' } )
See http://docs.python.org/library/functions.html#type
精彩评论