了解Python中的元类和继承

这个问题在这里已经有了答案:

  • Python中的元类是什么? 14个答案

  • 1)元类的用途以及何时使用它?

    元类是类,类是对象的类。 他们是类的类(因此表达“元”)。

    元类通常用于当您想在OOP的正常约束之外工作时。

    2)元类和继承之间有什么不同/相似之处?

    元类不是对象的类层次结构的一部分,而基类是。 所以当一个对象执行“obj.some_method()”时,它不会在元类中搜索这个方法,然而元类可能是在类或对象创建期间创建的。

    在下面的例子中,元类meta_car根据随机数为对象提供“缺陷”属性。 “缺陷”属性没有在任何对象的基类或类本身中定义。 但是,这可能仅使用类来实现。

    然而(与类不同),这个元类还重新路由了对象创建; 在some_cars列表中,所有的Toyotas都是使用Car类创建的。 元类检测到Car __init__包含一个make参数,该参数通过该名称匹配预先存在的类,并返回该类的对象。

    另外,您还会注意到,在some_cars列表中,使用make =“GM”调用Car __init__ 。 在该计划的评估中,GM类目前尚未定义。 元类在make参数中检测到该类不存在该名称,所以它创建一个并更新全局名称空间(因此它不需要使用返回机制)。 然后使用新定义的类创建对象并返回它。

    import random
    
    class CarBase(object):
        pass
    
    class meta_car(type):
        car_brands = {}
        def __init__(cls, cls_name, cls_bases, cls_dict):
            super(meta_car, cls).__init__(cls_name, cls_bases, cls_dict)
            if(not CarBase in cls_bases):
                meta_car.car_brands[cls_name] = cls
    
        def __call__(self, *args, **kwargs):
            make = kwargs.get("make", "")
            if(meta_car.car_brands.has_key(make) and not (self is meta_car.car_brands[make])):
                obj = meta_car.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 meta_car.car_brands.has_key(self.__name__)):
                    new_class = meta_car(make, (GenericCar,), {})
                    globals()[make] = new_class
                    obj = new_class(*args, **kwargs)
                else:
                    obj = super(meta_car, self).__call__(*args, **kwargs)
            return obj
    
    class Car(CarBase):
        __metaclass__ = meta_car
    
        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时几乎总是使用继承。 元类用于在这些约束之外工作(参考示例),几乎总是没有必要,但是可以使用它们来实现一些非常先进和非常动态的程序流程。 这是他们的力量和危险

    链接地址: http://www.djcxy.com/p/6981.html

    上一篇: Understanding metaclass and inheritance in Python

    下一篇: How to run code when a class is subclassed?