2015-06-18 12 views
5

Belirli kullanım durumum, pathlib.Path sınıfını alt sınıflara ayırmaya çalışıyorum. Bazı işlevleri ekleyebilmek veya geçersiz kılmak istiyorum ama aynı zamanda tüm Yol'u devralmak istiyorum. Yol bir __new__ sahiptir ve içinde vardır:__new__'ye sahip olan ve cls değerine dayanan bir sınıf nasıl alt sınıflara ayrılır?

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

Başka bir deyişle, Yol buna uygun sınıf geçme gerektirir. Sorun, MY sınıfını nasıl oluşturacağımı bilmiyorum ve'u cls == Path ile nasıl arayacağımı bilmiyorum.

Birçok şeyi denedim ve her biri bana farklı bir sorun veriyor. Bu bana AttributeError: type object 'RPath' has no attribute '_flavour' verdi, çünkü üst sınıfı geçersiz kılmaya çalışıyorum.

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') 

Ve bu benim geçersiz kılmaları yapmasına izin vermez, dolayısıyla döndürür bir yol nesnesini verir ve.

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

Ben de boşuna, super() çeşitli kullanımlarını çalıştı.

Bu oldukça kolay olmalı gibi görünüyor. Neyi kaçırıyorum?

Güncelleme: Neyi başarmaya çalışıyorum? Özellikle, class RPath(basedir, *pathsegments) yapmak istiyorum:

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

__new__ içine yerleştirmek istediğiniz işlevsellik nedir? – Meitham

+0

Burada yapmaya çalıştığınız şeyi netleştirmeniz gerekiyor. Korumaya çalıştığınız Path .__ new__ işlevinin işlevselliği, * farklı bir sınıf * oluşturacak, böylece kodun bu bölümünü çalıştırmaya karar verdiyseniz, alt sınıflarınız gider. –

+0

Yukarıda güncellendi. Üzgünüm yeterince açık değildim. Ve daha spesifik olarak, pathlib '__init__' diyor. Yani bir yerde ilk argüman 'class RPath (baselib, * pathsegments)' almak istiyorum ve '__new__''de' self.baselib = baselib' veya kendi '__init__''da ayarlamak istiyorum. –

cevap

2

O her zamanki gibi mümkün olacak sanmıyorum. Ama bunu yapabilseydiniz bile işe yaramıyordu, çünkü Yolun ne yaptığı da düz bir Yol döndürmüyor, bazı alt sınıflara (WindowsPath veya PosixPath) dönüyor. Bu nedenle, geçersiz kılınacak olan geçersiz kılmaları etkin olmayacaktır, çünkü Path.__new__'u devralmayı başarmış olsaydınız, yine de, WindowsPath ve WindowsPath, özel yol alt sınıfınızı değil, Yol'dan miras alır.

Görünüşe göre pathlib.Path kendine özgü bir sınıf yapısına sahiptir ve çoğaltmak için bazı özel işler yapmanız gerekir. İlk tahminde, kendi alt sınıflarınızı WindowsPath ve PosixPath yapmalı ve daha sonra, kendilerinden birini oluşturmak için delegelerin oluşturduğu bir Yol alt sınıfı oluşturmalısınız.

0

Burada, kalıtımı kullanmasa da a çözümü var. Hala bunu yapmak için basit, basit bir miras yolu olduğundan şüpheleniyorum (yine de BrenBarn'ın diğer tarafa verdiği cevaba bakınız).

Bu yöntem bileşimi kullanır. Anahtar, sarıcı sınıfında bulunmayan tüm istekleri otomatik olarak sarılmış sınıfa devretmek için __getattr__ ve getattr() kullanıyor. İşte bir örnek:

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

aslında çağırmak için kesinlikle hiçbir yükümlülük altında olduğunu hatırla üst sınıf en __new__ veya __init__. Tek kısıtlama, cls türünde bir nesneyi ayırmak için en sonunda object.__new__(cls)'u çağırmanızdır.

Bu nedenle, ilgili mantığı yalnızca kendi sınıfınızın __new__ ürününüzden kopyalayın.

İlgili konular