1443 字

Python 动态创建类 z

Python; Python; Class; ;

廖雪峰 Metaclass-ORM 个人理解

  1. 默认的类看不出是动态创建的;
  2. eval(), getattr 动态创建对象 - 见下面内容;
  3. 区分__getattr__()方法与getattr()函数;前者是访问不存在的属性时动态返回一个属性或函数,后者是返回指定类属性的取值;

  1. 廖雪峰的 ORM 的例子中中,Model里面只有非常抽象的save()等方法,在ModelMetaclass里面根据User中的属性动态创建映射关系,然后再实时返回一个创建好的具体的User类;
    1. Users中由使用者指定需要映射的具体条目,对于不同的使用者,要映射的条目不相同,比如现在要的是username, email,下次的场景就可能是user, password
    2. 即使要映射的条目相同,使用者定义的Users的属性名称也可能不同,比如有人是username,有人可能是userid
    3. 但我们不希望每次需求不同时,就重新定义一个面向特定需求的类,类中包含需要的各种属性;
  2. 分离出来的Model负责实现与数据库的交互,但Model不清楚究竟要与哪张表交互,有哪些字段;
  3. ModelMetaclass在 new Users 的时候,就把Users中指定好的条目对(本地条目、数据库表的字段)接管过来,保存好属性-字段关系,将其作为一部分参数重新传递给type()函数重新创建User类,也就是在Users()创建的时候拦截下来,做了修改之后再按规划创建一个规范的User
  4. User如果不用ModelMetaclass的话,其创建的时候,自身是无法知道接下来会有什么属性和属性名的。
  5. 这时User继承自ModelSave()其实在此之前并不知道会有哪些条目,但是经过ModelMetaclass之后,就可以从动态生成的__mappings__中获知这一点;
  6. 现在User只管根据需要即时创建好条目对,之后由ModelMetaclass创建修改后的类,创建初始化完成后,参数再传递到继承自ModelSave()方法,最后Save()根据收到的参数:对象的具体参数以及具体需要的条目对完成数据库操作。

  • User中只有条目对作为属性;
  • ModelMetaclass中只有__new__()
  • Model中包含具体的初始化以及业务逻辑。

利用 eval()

原文地址http://blog.chinaunix.net/uid-608135-id-3774614.htmlz

某些时候我们需要创建一个对象的时候,要根据运行环境来确定对象的类型,这个时候就需要一种方法来动态的创建对象,也就是说类的名字是不确定的。

def getObj(name):
    return eval(name+'()')

利用 getattr() 函数 - 未理解

比如

modulename = 'haha' #模块字符串

然后:

m = __import__(mymodule)

下面方法就可以用 Python 动态创建类。如果要取得模块中的一个属性的话:可以用getattr(),比如:

c = getattr(m, 'myclass') 
myobject = c()

但是要注意:如果myclass并不在mymodule的自动导出列表中(__all__),则必须显式地导入,例如:

m = __import__('mymodule', globals(), locals(), ['myclass']) 
c = getattr(m, 'myclass') 
myobject = c()

简单的可以用globals()[class_name]()

def create_obj(cls_name):
    names = cls_name.split(".")
    cls = globals()[names[0]]
    for name in names[1:]:
        cls = getattr(cls, name)

    if isinstance(cls, type):
        return cls()
    else:
        raise Exception("no such class")

如果要使用当前模块:

classname = 'blabla';
mod       = sys.modules[__name__];
dynclass  = getattr(mod, classname)
object    = dynclass(params);

利用 type()

利用 Metaclass + return type()

class in function - 不如 eval 彻底

代码出处https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python

如同 e-satis 所说的,这里的方案还不够动态,因为仍然需要自己编写整个类的代码。

>>> def choose_class(name):
…       if name == 'foo':
…           class Foo(object):
…               pass
…           return Foo          # 返回的是类,不是类的实例
…       else:
…           class Bar(object):
…               pass
…           return Bar
…
>>> MyClass = choose_class('foo')
>>> print MyClass               # 函数返回的是类,不是类的实例
<class '__main__'.Foo>
>>> print MyClass()             # 你可以通过这个类创建类实例,也就是对象
<__main__.Foo object at 0x89c6d4c>