元类和方法

时间:2017-06-22 21:56:03

标签: python metaprogramming self metaclass

在以下示例中,向元类添加方法非常有效。

class Test(object):

    def __init__(self, x):
        self.x = x

    def double(self):
        return self.x*2

# method to add
def quadruple(self):
    return self.x*4

# creating metaclass
TypeTest = type('TypeTest', (Test,), {'triple': triple, 
                                      'quadruple': quadruple})

# prints 8
TypeTest(2).quadruple()

以下示例不起作用,我不明白为什么。它只是在解析的函数中不识别self并且发生TypeError。

class Vehicle(object):
    def __init__(self, wheels, door=False):
        self.wheels = wheels
        self.door = door

# method to add
def check_load(self, x):
    if x > self.load:
        return "Load won't fit"
    else:
        return "Load will fit"

# creating metaclass
Truck = type('Truck', (Vehicle,), dict(wheels=4,door=True, load=100,
                                       check_load=check_load))

# TypeError: check_load() missing 1 required positional argument: 'x'
Truck.check_load(10)

1 个答案:

答案 0 :(得分:5)

首先:您创建元类,您正在创建常规类。 type()是这里的(基本)元类,调用它会创建一个新的类对象(class语句生成的对象类型相同)。

第一次type()电话基本上等同于:

class TypeTest(Test)
    triple = triple
    quadruple = quadruple

,第二个例子与:

相同
class Truck(Vehicle)
    wheels = 4
    door = True
    load = 100
    check_load = check_load

您忘记创建Truck课程的实例

Truck.check_load(10)

这使check_load()函数无法绑定,没有self

在您的第一个示例中, 创建了一个实例:

TypeTest(2).quadruple()

注意来电,传入2

为要绑定的self创建一个实例:

Truck(4, True).check_load(10)

如果您希望您的类不需要参数来创建实例,那么您还需要提供一个不同的__init__方法,一个覆盖Vehicle.__init__方法的方法:

def init(self): pass

Truck = type('Truck', (Vehicle,), dict(
    wheels=4,door=True, load=100,
    check_load=check_load, __init__=init))

现在您可以创建不带参数的实例:

Truck().check_load(10)