Python의 메타 클래스 및 상속 이해
이 질문에 이미 답변이 있습니다.
- 파이썬의 메타 클래스는 무엇입니까? 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
메타 클래스로
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) 메타 클래스의 사용은 무엇이며 언제 사용합니까?
메타 클래스는 클래스와 객체에 대한 클래스입니다. 클래스에 대한 클래스입니다 (따라서 "메타"라는 표현).
메타 클래스는 일반적으로 OOP의 일반적인 제약을 벗어나 작업하려는 경우에 사용됩니다.
2) 메타 클래스와 상속의 차이점 / 유사성은 무엇입니까?
메타 클래스는 객체의 클래스 계층 구조의 일부가 아니지만 기본 클래스는 있습니다. 따라서 객체가 수행 obj.some_method()
할 때이 메서드에 대한 메타 클래스를 검색 하지 않지만 메타 클래스가 클래스 또는 객체 생성 중에 생성했을 수 있습니다.
아래의이 예에서 메타 클래스 MetaCar
는 defect
난수를 기반으로하는 속성을 객체에 제공합니다 . defect
속성은 객체의 기본 클래스 나 클래스 자체의에 정의되어 있지 않습니다. 그러나 이것은 클래스만을 사용하여 달성 할 수 있습니다.
그러나 (클래스와 달리)이 메타 클래스는 객체 생성 경로도 다시 지정합니다. 에 some_cars
목록, 모든 토요타는 사용하여 만든 Car
클래스를. 메타 클래스는 해당 이름으로 기존 클래스와 일치 Car.__init__
하는 make
인수 가 포함 된 것을 감지하고 대신 해당 클래스의 객체를 반환합니다.
또한, 당신은 또한에 참고하겠습니다 some_cars
목록, Car.__init__
호출됩니다 make="GM"
. GM
클래스는 프로그램의 평가의이 시점에서 정의되지 않았습니다. 메타 클래스는 make 인수에서 해당 이름으로 클래스가 존재하지 않음을 감지하여 하나를 만들고 전역 네임 스페이스를 업데이트합니다 (반환 메커니즘을 사용할 필요가 없음). 그런 다음 새로 정의 된 클래스를 사용하여 객체를 생성하고 반환합니다.
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) 메타 클래스 나 상속은 어디에서 사용해야합니까?
As mentioned in this answer and in the comments, almost always use inheritance when doing OOP. Metaclasses are for working outside those constraints (refer to example) and is almost always not necessary however some very advanced and extremely dynamic program flow can be achieved with them. This is both their strength and their danger.
ReferenceURL : https://stackoverflow.com/questions/17801344/understanding-metaclass-and-inheritance-in-python
'Development Tip' 카테고리의 다른 글
Python에서 인스턴스 재 분류 (0) | 2020.12.31 |
---|---|
Haskell의 Priority Queue 구현 비교 (0) | 2020.12.31 |
PhoneGap 대 티타늄 (0) | 2020.12.31 |
IntelliJ Idea 12 + Android + Scala 요즘 (0) | 2020.12.31 |
페이지 매김을위한 ProgressBar가있는 Endless RecyclerView (0) | 2020.12.31 |