2013-05-30 1 views
4

str 유형과 두 번째 클래스 모두에서 상속되는 파생 클래스를 만들려고합니다. str 유형은 단순히 __init__을 호출하는 것이 아니고, 변경 불가능하기 때문에 __new__ 메서드를 호출하기 때문에 문제가 발생합니다. 나는 __init__과 super가 잘 작동한다는 것을 알고 있습니다. 동일한 호출 구조를 가지고 있어야합니다. 다음 구현이 실패 그러나 :와문자열과 두 번째 클래스가있는 __new__ 및 __init__의 Python 다중 상속

여기
class base(object): 
    def __new__(cls, *args, **kwargs): 
     print "NEW BASE:", cls, args, kwargs 
     return super(base, cls).__new__(cls, *args, **kwargs) 

    def __init__(self, *args, **kwargs): 
     print "INIT BASE", args, kwargs 

class foo(base, str): 
    def __new__(cls, *args, **kwargs): 
     return super(foo, cls).__new__(cls, *args, **kwargs) 

    def __init__(self, *args, **kwargs): 
     super(foo, self).__init__(*args, **kwargs) 

foo('cat') 작품 :

>> NEW BASE: <class '__main__.foo'> ('cat',) {} 
>> INIT BASE ('cat',) {} 

있지만 인수 foo('cat', x=3), 그것은 실패

>> NEW BASE: <class '__main__.foo'> ('cat',) {'x': 3} 
Traceback (most recent call last): 
    File "inh.py", line 19, in <module> 
    foo('cat', x=3) 
    File "inh.py", line 12, in __new__ 
    return super(foo, cls).__new__(cls, *args, **kwargs) 
    File "inh.py", line 4, in __new__ 
    return super(base, cls).__new__(cls, *args, **kwargs) 
TypeError: str() takes at most 1 argument (2 given) 

내가 이에 의해 작동시킬 수 있습니다 base.__new__ 방법을 다음으로 변경하십시오.

def __new__(cls, *args, **kwargs): 
    return super(base, cls).__new__(cls) 

하지만 이제는 호출 구조가 변경되었으므로 나중에 문제가 생길 것입니다.

문자열과 두 번째 클래스에서 올바르게 상속하는 방법? 이 STR의 새로운에 대한 잘못된 전화가 발생할 수 있기 때문에

답변

2

당신은 당신은

같은 것을해야

>>> foo('t') 
NEW BASE: <class '__main__.foo'> ('t',) {} 
INIT BASE ('t',) {} 
'' 

인수 (허용 된 패스하지 않습니다

def __new__(cls, *args, **kwargs): 
    return super(base, cls).__new__(cls) 

할 수 없습니다

def __new__(cls, *args, **kwargs): 
    return super(base, cls).__new__(cls, *args[:1]) 

하지만 __new__ 메서드가 둘 이상의 인수를 허용하는 클래스에 대해서는 mixin으로 base 클래스를 사용합니다. 어쩌면 당신은 클래스가 str에서 상속하지만 무시 새로운 방법이해야 할 옵션으로

:

class CarelessStr(str): 
    def __new__(cls, *args, **kwargs): 
     return super(CarelessStr, cls).__new__(cls, *args[:1]) 

class foo(base, CarelessStr): 
    def __new__(cls, *args, **kwargs): 
     return super(foo, cls).__new__(cls, *args, **kwargs) 

    def __init__(self, *args, **kwargs): 
     super(foo, self).__init__(*args, **kwargs) 
+0

당신은 나의 새로운 첫 번째 인수를 전달하지 않습니다 맞아요. 그러나 당신의 솔루션은 간접적 인 또 다른 계층을 추가하기 때문에 고통 스럽습니다. 틀림없이 그것은 작동하지만 파이썬 방법으로 간주됩니까? – Hooked

+0

설명 된 작업에 대한 일반적인 해결책이 있는지 확신하지 못합니다. 나는이 솔루션이 또 다른 간접적 인 계층을 추가한다는 것에 동의한다. 그러나 이것은 몇몇 경우에 대한 유일한 선택 일 수 있습니다. – oleg

+0

굉장합니다. 여분의 str 기초는 나에게 발생하지 않고 있었다! – Rafe