Understanding metaclass and inheritance in Python
本问题已经有最佳答案,请猛点这里访问。
关于元类,我有些困惑。
有继承权1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | class AttributeInitType(object): def __init__(self,**kwargs): for name, value in kwargs.items(): setattr(self, name, value) class Car(AttributeInitType): def __init__(self,**kwargs): super(Car, self).__init__(**kwargs) @property def description(self): return"%s %s %s %s" % (self.color, self.year, self.make, self.model) c = Car(make='Toyota', model='Prius', year=2005, color='green') print c.description |
元类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class AttributeInitType(type): def __call__(self, *args, **kwargs): obj = type.__call__(self, *args) for name, value in kwargs.items(): setattr(obj, name, value) return obj class Car(object): __metaclass__ = AttributeInitType @property def description(self): return"%s %s %s %s" % (self.color, self.year, self.make, self.model) c = Car(make='Toyota', model='Prius', year=2005,color='blue') print c.description |
上面的例子并没有实际意义上的有用,只是为了理解,
我有一些问题,比如,
元类的用途是什么?我什么时候使用它?
元类和继承之间的区别/相似之处是什么?
应该在哪里使用元类或继承?
1)元类的用途是什么,以及何时使用它?
元类是对类的,类是对对象的。它们是类的类(因此表达式"meta")。
元类通常用于在OOP的正常约束之外工作的情况。
2)元类和继承的区别/相似之处是什么?
元类不是对象类层次结构的一部分,而基类是。因此,当一个对象执行
在下面的示例中,元类
但是(与类不同),这个元类也重新路由对象创建;在
此外,您还将注意到在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | import random class CarBase(object): pass class MetaCar(type): car_brands = {} def __init__(cls, cls_name, cls_bases, cls_dict): super(MetaCar, cls).__init__(cls_name, cls_bases, cls_dict) if(not CarBase in cls_bases): MetaCar.car_brands[cls_name] = cls def __call__(self, *args, **kwargs): make = kwargs.get("make","") if(MetaCar.car_brands.has_key(make) and not (self is MetaCar.car_brands[make])): obj = MetaCar.car_brands[make].__call__(*args, **kwargs) if(make =="Toyota"): if(random.randint(0, 100) < 2): obj.defect ="sticky accelerator pedal" elif(make =="GM"): if(random.randint(0, 100) < 20): obj.defect ="shithouse" elif(make =="Great Wall"): if(random.randint(0, 100) < 101): obj.defect ="cancer" else: obj = None if(not MetaCar.car_brands.has_key(self.__name__)): new_class = MetaCar(make, (GenericCar,), {}) globals()[make] = new_class obj = new_class(*args, **kwargs) else: obj = super(MetaCar, self).__call__(*args, **kwargs) return obj class Car(CarBase): __metaclass__ = MetaCar def __init__(self, **kwargs): for name, value in kwargs.items(): setattr(self, name, value) def __repr__(self): return"<%s>" % self.description @property def description(self): return"%s %s %s %s" % (self.color, self.year, self.make, self.model) class GenericCar(Car): def __init__(self, **kwargs): kwargs["make"] = self.__class__.__name__ super(GenericCar, self).__init__(**kwargs) class Toyota(GenericCar): pass colours = \\ [ "blue", "green", "red", "yellow", "orange", "purple", "silver", "black", "white" ] def rand_colour(): return colours[random.randint(0, len(colours) - 1)] some_cars = \\ [ Car(make="Toyota", model="Prius", year=2005, color=rand_colour()), Car(make="Toyota", model="Camry", year=2007, color=rand_colour()), Car(make="Toyota", model="Camry Hybrid", year=2013, color=rand_colour()), Car(make="Toyota", model="Land Cruiser", year=2009, color=rand_colour()), Car(make="Toyota", model="FJ Cruiser", year=2012, color=rand_colour()), Car(make="Toyota", model="Corolla", year=2010, color=rand_colour()), Car(make="Toyota", model="Hiace", year=2006, color=rand_colour()), Car(make="Toyota", model="Townace", year=2003, color=rand_colour()), Car(make="Toyota", model="Aurion", year=2008, color=rand_colour()), Car(make="Toyota", model="Supra", year=2004, color=rand_colour()), Car(make="Toyota", model="86", year=2013, color=rand_colour()), Car(make="GM", model="Camaro", year=2008, color=rand_colour()) ] dodgy_vehicles = filter(lambda x: hasattr(x,"defect"), some_cars) print dodgy_vehicles |
3)应该在哪里使用元类或继承?
正如这个答案和注释中提到的,在进行OOP时几乎总是使用继承。元类用于在这些约束之外工作(请参阅示例),并且几乎总是不必要的,但是可以使用它们实现一些非常高级和非常动态的程序流。这既是他们的力量,也是他们的危险。