2015-06-18 9 views
5

W moim konkretnym przypadku użycia próbuję podklasy pathlib.Path. Chcę móc dodawać lub zastępować niektóre funkcje, ale chcę też dziedziczyć całą ścieżkę. Ścieżka ma __new__ aw niej posiada:Jak podklasować klasę, która ma __new__ i opiera się na wartości cls?

if cls is Path: 
    cls = WindowsPath if os.name == 'nt' else PosixPath 

Innymi słowy, droga wymaga podjęcia właściwej klasy do niego. Problem polega na tym, że nie wiem, jak utworzyć MOJĄ klasę i zadzwonić pod numer Path.__new__ z cls == Path.

Próbowałem wielu rzeczy, a każdy z nich stwarza inny problem. Ten daje mi AttributeError: type object 'RPath' has no attribute '_flavour', ponieważ próbuję przesłonić klasy nadrzędnej.

Python3:

class RPath(Path): 
    def __new__(cls, basedir, *args, **kwargs): 
     return Path.__new__(cls, *args, **kwargs) 

    def __init__(self, basedir, *pathsegs): 
     super().__init__() 
     self.basedir = basedir 

    def newfunction(self): 
     print('Something new') 

A ten daje Zwraca obiekt Path, a tym samym nie pozwala mi zrobić moje przesłonięcia.

def __new__(cls, basedir, *args, **kwargs): 
    return Path.__new__(Path, *args, **kwargs) 

Próbowałem również różnych zastosowań super(), na próżno.

Wygląda na to, że powinno być całkiem łatwe. czego mi brakuje?

Aktualizacja: Co staram się osiągnąć? szczególności chcę, aby class RPath(basedir, *pathsegments):

rpath=RPath('\root\dir', 'relpath\path2\file.ext) 
assert rpath.basedir == '\root\dir' # True 
rpath.rebase('\new_basedir') 
assert rpath.basedir === '\newbasedir' # True 
# And while I'm at it 
assert rpath.str == str(rpath) # make str a property == __str__(self) 
+0

Jaka jest dokładna funkcja, którą chcesz wstawić do __new__? – Meitham

+0

Musisz wyjaśnić, co próbujesz tutaj zrobić. Funkcjonalność z 'Path .__ new__', którą próbujesz zachować, stworzy * inną klasę *, więc jeśli udało ci się uruchomić tę część kodu, twoja podklasa zniknie. –

+0

Zaktualizowane powyżej. Przepraszam, nie byłem wystarczająco jasny. A dokładniej, pathlib nie nazywa się '__init__'. Więc gdzieś chcę wziąć pierwszy argument 'class RPath (baselib, * pathsegments)' i ustawić 'self.baselib = baselib' w' __new__' lub we własnym '__init__'. –

Odpowiedz

2

nie sądzę, że będzie to możliwe w zwykły sposób. Ale nawet gdybyś mógł to zrobić, to by nie działało, ponieważ co robi Ścieżka, nie zwraca prostej ścieżki, to zwraca jakąś podklasę (WindowsPath lub PosixPath). Tak więc przesłonięcia do ścieżki nie zostaną uwzględnione, ponieważ gdyby można było dziedziczyć Path.__new__, nadal powróciłoby, powiedzmy, do WindowsPath, a ścieżka WindowsPath dziedziczy po ścieżce, a nie podklasie ścieżki niestandardowej.

Wygląda na to, że pathlib.Path ma specyficzną strukturę klasy, i będziesz musiał wykonać specjalną pracę, aby ją powielić. Na pierwszy rzut oka musiałbyś stworzyć własną podklasę WindowsPath i PosixPath, a następnie stworzyć podklasę Path, która deleguje, aby utworzyć jedno z nich zamiast siebie.

0

Oto rozwiązanie, ale nie korzysta z dziedziczenia. Nadal podejrzewam, że istnieje prosty sposób, aby to zrobić (chociaż zobacz odpowiedź BrenBarn na drugą stronę).

Ta metoda używa składu. Kluczem jest użycie __getattr__ i getattr(), aby automatycznie delegować wszystkie żądania nie znalezione w klasie opakowania do zawiniętej klasy. Oto przykład:

class RPath(object): 
    def __init__(self, basedir, *pathsegs): 
     self.p = Path(*pathsegs) 
     self.basedir = basedir 

    # Override existing behavior 
    def __eq__(self, other): 
     return type(other) is RPath and self.basedir == other.basedir and self.p == other.p  

    # Add new behavior 
    def cp(self): 
     return self.basedir/self.p  

    # Everything not found here, automatically delegate to Path 
    def __getattr__(self, attr): 
     return getattr(self.cp, attr) 
0

Pamiętaj, że jesteś pod absolutnie nie obowiązek faktycznie nazwać swoją nadklasą na __new__ lub __init__. Jedynym ograniczeniem jest, aby ostatecznie zadzwonić pod numer object.__new__(cls), aby przydzielić obiekt typu cls.

Po prostu skopiuj odpowiednią logikę z twojej nadklasy __new__ do swojej własnej.

Powiązane problemy