Python salt okunur özelliği


97

Özniteliğin ne zaman özel olması gerektiğini ve mülk kullanmalı mıyım bilmiyorum.

Geçenlerde ayarlayıcıların ve alıcıların pitonik olmadığını ve mülk dekoratörü kullanmam gerektiğini okudum. Tamam.

Ama ya özniteliğim varsa, bu sınıfın dışından ayarlanmamalıdır, ancak okunabilir (salt okunur öznitelik). Bu özellik özel mi olmalı ve özel derken alt çizgi ile self._xmi demek istiyorum, böyle mi? Cevabınız evet ise, alıcı kullanmadan nasıl okuyabilirim? Şu anda bildiğim tek yöntem yazmak

@property
def x(self):
    return self._x

Bu şekilde özelliği okuyabilirim, obj.xancak ayarlayamıyorum, bu obj.x = 1yüzden sorun değil.

Ama ayarlanmaması gereken nesneyi ayarlamayı gerçekten önemsemeli miyim? Belki de bırakmalıyım. Ama yine de alt çizgi kullanamam çünkü okumak obj._xkullanıcı için tuhaftır, bu yüzden kullanmalıyım obj.xve yine kullanıcı bu özelliği ayarlamaması gerektiğini bilmiyor.

Fikriniz ve pratikleriniz nedir?


1
Bir özellik fikri, bir nitelik gibi davranması, ancak fazladan koda sahip olabilmesidir. Tek istediğiniz bir değer elde etmekse, zahmet bile etmem: sadece kullanın self.xve kimsenin değişmeyeceğine güvenin x. xBunun değiştirilemeyeceğinden emin olmak önemliyse, bir özellik kullanın.
li.davidm

Ayrıca, _xhiç de tuhaf değil: geleneksel olarak , "özel" bir şey ifade ediyor.
li.davidm

1
_X'ten okumanın tuhaf olduğunu kastetmiştim. _X kendisini adlandırmaz. Kullanıcı doğrudan _x'ten okuyorsa sorumsuzdur.
Rafał Łużyński

3
Önemli! Sınıfınız yeni stil bir sınıf olmalıdır object, yani bunun ayarlamanızı gerçekten durdurması için sınıftan miras almalıdır obj.x. Eski tarz bir sınıfta obj.x, oldukça beklenmedik sonuçlarla aslında hala ayarlayabilirsiniz .
Ian H

Salt okunur özelliklere sahip olmanın birkaç geçerli nedeni vardır. Biri, diğer iki (okuma / yazma) değerin birleştirilmesinden oluşan bir değere sahip olduğunuz zamandır. Bunu bir yöntemde yapabilirsiniz, ancak bunu salt okunur özellikte de yapabilirsiniz.
philologon

Yanıtlar:


73

Genel olarak, Python programları, tüm kullanıcıların yetişkinlere rıza gösterdiği ve bu nedenle de nesneleri doğru kullanmaktan sorumlu oldukları varsayımıyla yazılmalıdır. Bununla birlikte, bir özniteliğin ayarlanabilir olmasının (türetilmiş bir değer veya bazı statik veri kaynaklarından okunan bir değer gibi) anlamlı olmadığı nadir durumlarda, yalnızca alıcı özelliği genellikle tercih edilen modeldir.


26
Görünüşe göre cevabınız kendisiyle çelişiyor. Kullanıcıların sorumlu olması ve işleri doğru kullanması gerektiğini söylüyorsunuz, o zaman bazen bir özniteliğin ayarlanabilir olmasının bir anlam ifade etmediğini ve alıcı özelliğinin tercih edilen bir yol olduğunu söylüyorsunuz. Benim görüşüme göre, nitelik belirleyebilir ya da ayarlayamazsınız. Tek soru, bu özü korumalı mıyım yoksa bırakmalı mıyım? Arada cevap olmamalı.
Rafał Łużyński

20
Hayır, kelimenin tam anlamıyla bir değer ayarlayamıyorsanız, bir ayarlayıcıya sahip olmanın bir anlamı olmadığını söyledim. Örneğin, bir yarıçap üyesine ve yarıçaptan türetilmiş bir çevre niteliğine sahip bir daire nesneniz varsa veya bazı salt okunur gerçek zamanlı API'leri bir dizi yalnızca alıcı özelliği ile saran bir nesneniz varsa. Hiçbir şeyle çelişen bir şey yok.
Silas Ray

9
Ancak sorumlu kullanıcı, kelimenin tam anlamıyla ayarlanamayacak bir özelliği ayarlamaya çalışmayacaktır. Ve yine sorumlu olmayan kullanıcı, kelimenin tam anlamıyla ayarlanabilen bir attr ayarlayacaktır ve setinden dolayı kodda başka bir yerde hata verecektir. Yani sonunda her iki özellik ayarlanamaz. Mülkü her ikisinde de kullanmalı mıyım yoksa hiçbirinde kullanmamalı mıyım?
Rafał Łużyński

8
Ancak bundan sorumlu kullanıcı olmamalıdır anlamıyla kümesi olamaz set attr deneyin. Programlamada, eğer bir şey kesinlikle ayarlanamayan bir değer ise, sorumlu veya mantıklı olan şey bunun olamayacağından emin olmaktır. Bu küçük şeylerin hepsi güvenilir programlara katkıda bulunur.
Robin Smith

6
Bu, birçok insanın ve dilin aldığı bir pozisyondur. Pazarlık edilemez bulduğunuz bir konumsa, muhtemelen Python kullanmamalısınız.
Silas Ray

75

Sadece iki sentim, Silas Ray doğru yolda, ancak bir örnek eklemek istedim. ;-)

Python, tür açısından güvenli olmayan bir dildir ve bu nedenle, kodu makul (mantıklı) bir kişi gibi kullanmak için kodunuzun kullanıcılarına her zaman güvenmeniz gerekir.

Başına PEP 8 :

Yalnızca genel olmayan yöntemler ve örnek değişkenleri için bir önde gelen alt çizgi kullanın.

Bir sınıfta "salt okunur" bir özelliğe sahip olmak için @propertydekorasyondan objectyararlanabilirsiniz, yeni stil sınıflarını kullanmak için bunu yaptığınız andan itibaren miras almanız gerekir .

Misal:

>>> class A(object):
...     def __init__(self, a):
...         self._a = a
...
...     @property
...     def a(self):
...         return self._a
... 
>>> a = A('test')
>>> a.a
'test'
>>> a.a = 'pleh'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: can't set attribute

9
Python tip güvenli değildir, dinamik olarak yazılmıştır. Ve adın karıştırılması hile yapmayı zorlaştırmak için değil, mirasın sorunlu olabileceği senaryolarda isim çatışmalarını önlemek içindir (eğer büyük ölçüde programlama yapmıyorsanız, umursamamalısınız bile).
memeplex

3
Ancak yine de, değiştirilebilir nesnelerin bu yöntem kullanılarak değiştirilebileceğini unutmamalısınız. Örneğin self.__a = [], bunu hala yapabilirseniz a.a.append('anything')işe yarayacaktır.
Igor

3
Bu cevaba "mantıklı (mantıklı) bir kişinin" neyi kattığı bana açık değil. Makul bir kişinin yapıp yapmayacağını düşündüğünüz şeyler hakkında daha açık olabilir misiniz?
winni2k

3
Benim için @ özelliği dekorasyonunu kullanıyorum, bunu yaptığınızda nesneden miras almanız gerekecek , bu cevabın tek amacı buydu. Teşekkürler.
akki

2
@kkm bir hatanın koda gizlice girmesine asla izin vermenin tek yolu asla kod yazmamaktır.
Alechan

58

İşte varsayımdan kaçınmanın bir yolu

tüm kullanıcılar rıza gösteren yetişkinlerdir ve bu nedenle nesneleri doğru kullanmaktan kendileri sorumludur.

lütfen aşağıdaki güncellememe bakın

Kullanmak @propertyçok ayrıntılıdır, örneğin:

   class AClassWithManyAttributes:
        '''refactored to properties'''
        def __init__(a, b, c, d, e ...)
             self._a = a
             self._b = b
             self._c = c
             self.d = d
             self.e = e

        @property
        def a(self):
            return self._a
        @property
        def b(self):
            return self._b
        @property
        def c(self):
            return self._c
        # you get this ... it's long

Kullanma

Alt çizgi yok: bu genel bir değişkendir.
Bir alt çizgi: korumalı bir değişkendir.
İki alt çizgi: özel bir değişkendir.

Sonuncusu hariç, bu bir kongre. Yine de, gerçekten çok denerseniz, değişkenlere çift alt çizgi ile erişebilirsiniz.

Peki ne yapıyoruz? Python'da salt okunur özelliklere sahip olmaktan vazgeçiyor muyuz?

Seyretmek! read_only_propertieskurtarmaya dekoratör!

@read_only_properties('readonly', 'forbidden')
class MyClass(object):
    def __init__(self, a, b, c):
        self.readonly = a
        self.forbidden = b
        self.ok = c

m = MyClass(1, 2, 3)
m.ok = 4
# we can re-assign a value to m.ok
# read only access to m.readonly is OK 
print(m.ok, m.readonly) 
print("This worked...")
# this will explode, and raise AttributeError
m.forbidden = 4

Sen sor:

Nereden read_only_propertiesgeliyor?

Sormanıza sevindim, read_only_properties için kaynak :

def read_only_properties(*attrs):

    def class_rebuilder(cls):
        "The class decorator"

        class NewClass(cls):
            "This is the overwritten class"
            def __setattr__(self, name, value):
                if name not in attrs:
                    pass
                elif name not in self.__dict__:
                    pass
                else:
                    raise AttributeError("Can't modify {}".format(name))

                super().__setattr__(name, value)
        return NewClass
    return class_rebuilder

Güncelleme

Bu cevabın bu kadar dikkat çekeceğini hiç beklemiyordum. Şaşırtıcı bir şekilde öyle. Bu, kullanabileceğiniz bir paket oluşturmam için beni cesaretlendirdi.

$ pip install read-only-properties

python kabuğunuzda:

In [1]: from rop import read_only_properties

In [2]: @read_only_properties('a')
   ...: class Foo:
   ...:     def __init__(self, a, b):
   ...:         self.a = a
   ...:         self.b = b
   ...:         

In [3]: f=Foo('explodes', 'ok-to-overwrite')

In [4]: f.b = 5

In [5]: f.a = 'boom'
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-a5226072b3b4> in <module>()
----> 1 f.a = 'boom'

/home/oznt/.virtualenvs/tracker/lib/python3.5/site-packages/rop.py in __setattr__(self, name, value)
    116                     pass
    117                 else:
--> 118                     raise AttributeError("Can't touch {}".format(name))
    119 
    120                 super().__setattr__(name, value)

AttributeError: Can't touch a

1
Bu gerçekten yardımcı oldu ve tam olarak yapmak istediğim şeyi yapıyor. Teşekkür ederim. Ancak, Python 3 kurulu olanlar içindir. Python 2.7.8 kullanıyorum, bu nedenle çözümünüze iki küçük ayar uygulamam gerekiyor: "class NewClass (cls, <b> object <\ b>):" ... "<b> super (NewClass, self) <\ b> .__ setattr __ (ad, değer) ".
Ying Zhang

1
Ek olarak, sınıf üyesi değişkenlerin listeler ve sözlükler olmasına dikkat edilmelidir. Bu şekilde güncellenmelerini gerçekten 'kilitleyemezsiniz'.
Ying Zhang

1
Burada bir gelişme ve üç sorun var. İyileştirme: if..elif..elseblok sadece olabilir if name in attrs and name in self.__dict__: raise Attr...hayır ile passgerekli. Problem 1: Bu şekilde dekore edilmiş sınıfların tümü bir özdeştir __name__ve türlerinin dizi gösterimi de homojenleştirilir. Problem 2: Bu dekorasyon herhangi bir geleneğin üzerine yazıyor __setattr__. Sorun 3: Kullanıcılar bunu ile yenebilir del MyClass.__setattr__.
TigerhawkT3

Sadece bir dil meselesi. "Ne yazık ki ..." demek "üzücü ..." demek istediğin bu değil sanırım.
Thomas Andrews

Yapmamı hiçbir şey engelleyemez object.__setattr__(f, 'forbidden', 42). read_only_propertiesÇift alt çizgi adının karıştırılmasıyla işlenmeyen ekleri göremiyorum .
L3viathan

4

Burada, salt okunur özelliklere biraz farklı bir yaklaşım var, buna belki de başlatılmaları gerektiğinden bir kez yazılır özellikleri denmesi gerekiyor, değil mi? Aramızdaki paranoyak kişiler için, doğrudan nesnenin sözlüğüne erişerek özellikleri değiştirebilmekten endişe duyan "ekstrem" ad karıştırmayı tanıttım:

from uuid import uuid4

class Read_Only_Property:
    def __init__(self, name):
        self.name = name
        self.dict_name = uuid4().hex
        self.initialized = False

    def __get__(self, instance, cls):
        if instance is None:
            return self
        else:
            return instance.__dict__[self.dict_name]

    def __set__(self, instance, value):
        if self.initialized:
            raise AttributeError("Attempt to modify read-only property '%s'." % self.name)
        instance.__dict__[self.dict_name] = value
        self.initialized = True

class Point:
    x = Read_Only_Property('x')
    y = Read_Only_Property('y')
    def __init__(self, x, y):
        self.x = x
        self.y = y

if __name__ == '__main__':
    try:
        p = Point(2, 3)
        print(p.x, p.y)
        p.x = 9
    except Exception as e:
        print(e)

Güzel. Eğer parçalamaya ise dict_namebunun yerine, örneğin dict_name = "_spam_" + nameo bağımlılığını kaldırır uuid4ve çok daha kolay hata ayıklama yapar.
cz

Ama sonra p.__dict__['_spam_x'] = 5değerini değiştirmeyi söyleyebilirim p.x, bu yüzden bu isim karıştırmaya yetmiyor.
Booboo

1

Salt okunur özellikler oluşturmak için önceki iki yanıttan memnun değilim çünkü ilk çözüm salt okunur özniteliğin silinmesine ve sonra ayarlanmasına izin veriyor ve __dict__ öğesini engellemiyor. İkinci çözüm, test etmekle, ikiye ayarladığınız şeye eşit olan değeri bulmak ve sonunda değiştirmekle çalışılabilir.

Şimdi, kod için.

def final(cls):
    clss = cls
    @classmethod
    def __init_subclass__(cls, **kwargs):
        raise TypeError("type '{}' is not an acceptable base type".format(clss.__name__))
    cls.__init_subclass__ = __init_subclass__
    return cls


def methoddefiner(cls, method_name):
    for clss in cls.mro():
        try:
            getattr(clss, method_name)
            return clss
        except(AttributeError):
            pass
    return None


def readonlyattributes(*attrs):
    """Method to create readonly attributes in a class

    Use as a decorator for a class. This function takes in unlimited 
    string arguments for names of readonly attributes and returns a
    function to make the readonly attributes readonly. 

    The original class's __getattribute__, __setattr__, and __delattr__ methods
    are redefined so avoid defining those methods in the decorated class

    You may create setters and deleters for readonly attributes, however
    if they are overwritten by the subclass, they lose access to the readonly
    attributes. 

    Any method which sets or deletes a readonly attribute within
    the class loses access if overwritten by the subclass besides the __new__
    or __init__ constructors.

    This decorator doesn't support subclassing of these classes
    """
    def classrebuilder(cls):
        def __getattribute__(self, name):
            if name == '__dict__':
                    from types import MappingProxyType
                    return MappingProxyType(super(cls, self).__getattribute__('__dict__'))
            return super(cls, self).__getattribute__(name)
        def __setattr__(self, name, value): 
                if name == '__dict__' or name in attrs:
                    import inspect
                    stack = inspect.stack()
                    try:
                        the_class = stack[1][0].f_locals['self'].__class__
                    except(KeyError):
                        the_class = None
                    the_method = stack[1][0].f_code.co_name
                    if the_class != cls: 
                         if methoddefiner(type(self), the_method) != cls:
                            raise AttributeError("Cannot set readonly attribute '{}'".format(name))                        
                return super(cls, self).__setattr__(name, value)
        def __delattr__(self, name):                
                if name == '__dict__' or name in attrs:
                    import inspect
                    stack = inspect.stack()
                    try:
                        the_class = stack[1][0].f_locals['self'].__class__
                    except(KeyError):
                        the_class = None
                    the_method = stack[1][0].f_code.co_name
                    if the_class != cls:
                        if methoddefiner(type(self), the_method) != cls:
                            raise AttributeError("Cannot delete readonly attribute '{}'".format(name))                        
                return super(cls, self).__delattr__(name)
        clss = cls
        cls.__getattribute__ = __getattribute__
        cls.__setattr__ = __setattr__
        cls.__delattr__ = __delattr__
        #This line will be moved when this algorithm will be compatible with inheritance
        cls = final(cls)
        return cls
    return classrebuilder

def setreadonlyattributes(cls, *readonlyattrs):
    return readonlyattributes(*readonlyattrs)(cls)


if __name__ == '__main__':
    #test readonlyattributes only as an indpendent module
    @readonlyattributes('readonlyfield')
    class ReadonlyFieldClass(object):
        def __init__(self, a, b):
            #Prevent initalization of the internal, unmodified PrivateFieldClass
            #External PrivateFieldClass can be initalized
            self.readonlyfield = a
            self.publicfield = b


    attr = None
    def main():
        global attr
        pfi = ReadonlyFieldClass('forbidden', 'changable')
        ###---test publicfield, ensure its mutable---###
        try:
            #get publicfield
            print(pfi.publicfield)
            print('__getattribute__ works')
            #set publicfield
            pfi.publicfield = 'mutable'
            print('__setattr__ seems to work')
            #get previously set publicfield
            print(pfi.publicfield)
            print('__setattr__ definitely works')
            #delete publicfield
            del pfi.publicfield 
            print('__delattr__ seems to work')
            #get publicfield which was supposed to be deleted therefore should raise AttributeError
            print(pfi.publlicfield)
            #publicfield wasn't deleted, raise RuntimeError
            raise RuntimeError('__delattr__ doesn\'t work')
        except(AttributeError):
            print('__delattr__ works')


        try:
            ###---test readonly, make sure its readonly---###
            #get readonlyfield
            print(pfi.readonlyfield)
            print('__getattribute__ works')
            #set readonlyfield, should raise AttributeError
            pfi.readonlyfield = 'readonly'
            #apparently readonlyfield was set, notify user
            raise RuntimeError('__setattr__ doesn\'t work')
        except(AttributeError):
            print('__setattr__ seems to work')
            try:
                #ensure readonlyfield wasn't set
                print(pfi.readonlyfield)
                print('__setattr__ works')
                #delete readonlyfield
                del pfi.readonlyfield
                #readonlyfield was deleted, raise RuntimeError
                raise RuntimeError('__delattr__ doesn\'t work')
            except(AttributeError):
                print('__delattr__ works')
        try:
            print("Dict testing")
            print(pfi.__dict__, type(pfi.__dict__))
            attr = pfi.readonlyfield
            print(attr)
            print("__getattribute__ works")
            if pfi.readonlyfield != 'forbidden':
                print(pfi.readonlyfield)
                raise RuntimeError("__getattr__ doesn't work")
            try:
                pfi.__dict__ = {}
                raise RuntimeError("__setattr__ doesn't work")
            except(AttributeError):
                print("__setattr__ works")
            del pfi.__dict__
            raise RuntimeError("__delattr__ doesn't work")
        except(AttributeError):
            print(pfi.__dict__)
            print("__delattr__ works")
            print("Basic things work")


main()

Uygulama geliştirme gibi başka herhangi bir amaç için kod değil, programlarını geliştirmek için kullanmak üzere başkalarına kod olarak dağıtılan kitaplık kodu yazmanız dışında salt okunur nitelikler yapmanın bir anlamı yoktur . __Dict__ problemi çözüldü, çünkü __dict__ artık değişmez türlerden.MappingProxyType , bu nedenle öznitelikler __dict__ ile değiştirilemez. __Dict__’ın ayarlanması veya silinmesi de engellenir. Salt okunur özellikleri değiştirmenin tek yolu, sınıfın kendi yöntemlerini değiştirmektir.

Çözümümün önceki ikisinden daha iyi olduğuna inansam da iyileştirilebilir. Bunlar bu kodun zayıf yönleridir:

a) Bir alt sınıfta salt okunur bir özniteliği ayarlayan veya silen bir yönteme eklemeye izin vermez. Bir alt sınıfta tanımlanan bir yöntemin, yöntemin süper sınıf sürümünün çağrılmasıyla bile, salt okunur özelliğe erişmesi otomatik olarak engellenir.

b) Sınıfın salt okunur yöntemleri, salt okunur kısıtlamaları ortadan kaldırmak için değiştirilebilir.

Ancak, sınıfı düzenlemeden salt okunur bir niteliği ayarlamanın veya silmenin yolu yoktur. Bu, adlandırma kurallarına bağlı değildir, bu iyidir çünkü Python adlandırma kurallarıyla o kadar tutarlı değildir. Bu, sınıfın kendisini düzenlemeden gizli boşluklarla değiştirilemeyen salt okunur nitelikler yapmanın bir yolunu sağlar. Sadece dekoratör argüman olarak çağrıldığında okunacak nitelikleri listeleyin ve bunlar salt okunur hale gelecektir.

Python'da başka bir sınıfın bir işlevi içinde arayan sınıfın adı nasıl alınır? arayan sınıflarını ve yöntemlerini almak için.


object.__setattr__(pfi, 'readonly', 'foobar')sınıfın kendisini düzenlemeden bu çözümü bozar.
L3viathan

0

Örnek yöntemlerin aynı zamanda öznitelikler (sınıfın) olduğuna ve gerçekten bir baş belası olmak istiyorsanız bunları sınıf veya örnek düzeyinde ayarlayabileceğinize dikkat edin. Veya kullanışlı salt okunur özelliklerin kutudan çıkar çıkmaz düzgün çalışmayacağı bir sınıf değişkeni (bu aynı zamanda sınıfın bir özniteliğidir) ayarlayabilirsiniz. Söylemeye çalıştığım şey, "salt okunur öznitelik" sorununun aslında genellikle algılandığından daha genel olduğudur. Neyse ki, işte bu diğer durumlar karşısında bizi kör edecek kadar güçlü olan geleneksel beklentiler var (sonuçta, neredeyse her şey python'da bir tür niteliktir).

Bu beklentilere dayanarak, bence en genel ve hafif yaklaşım, "genel" (önde gelen alt çizgi yok) özniteliklerin, yazılabilir olarak açıkça belgelendiği durumlar dışında salt okunur olduğu kuralını benimsemek olduğunu düşünüyorum. Bu, yöntemlerin yamalanmayacağı ve örnek varsayılanlarını gösteren sınıf değişkenlerinin bir yana daha iyi olacağı yönündeki olağan beklentiyi kapsar. Bazı özel nitelikler konusunda gerçekten paranoyak hissediyorsanız, son kaynak ölçüsü olarak bir salt okunur tanımlayıcı kullanın.


0

Oz123'ün sınıf tasarımcısını sevsem de, açık bir sınıf sarmalayıcısı kullanan ve __new__ sınıfını bir kapanış içinde döndüren bir sınıf Factory yöntemi ile kullanan aşağıdakileri de yapabilirsiniz:

class B(object):
    def __new__(cls, val):
        return cls.factory(val)

@classmethod
def factory(cls, val):
    private = {'var': 'test'}

    class InnerB(object):
        def __init__(self):
            self.variable = val
            pass

        @property
        def var(self):
            return private['var']

    return InnerB()

birden çok
mülkle

0

Bu benim çözümüm.

@property
def language(self):
    return self._language
@language.setter
def language(self, value):
    # WORKAROUND to get a "getter-only" behavior
    # set the value only if the attribute does not exist
    try:
        if self.language == value:
            pass
        print("WARNING: Cannot set attribute \'language\'.")
    except AttributeError:
        self._language = value

0

birisi proxy nesnesi kullandığından bahsetti, bunun bir örneğini görmedim, bu yüzden denemeye başladım, [kötü].

/! \ Mümkünse lütfen sınıf tanımlarını ve sınıf yapıcılarını tercih edin

bu kod, class.__new__her yönden daha kötüsü dışında , etkin bir şekilde yeniden yazılıyor (sınıf oluşturucu). Kendinizi acıdan kurtarın ve yapabiliyorsanız bu kalıbı kullanmayın.

def attr_proxy(obj):
    """ Use dynamic class definition to bind obj and proxy_attrs.
        If you can extend the target class constructor that is 
        cleaner, but its not always trivial to do so.
    """
    proxy_attrs = dict()

    class MyObjAttrProxy():
        def __getattr__(self, name):
            if name in proxy_attrs:
                return proxy_attrs[name]  # overloaded

            return getattr(obj, name)  # proxy

        def __setattr__(self, name, value):
            """ note, self is not bound when overloading methods
            """
            proxy_attrs[name] = value

    return MyObjAttrProxy()


myobj = attr_proxy(Object())
setattr(myobj, 'foo_str', 'foo')

def func_bind_obj_as_self(func, self):
    def _method(*args, **kwargs):
        return func(self, *args, **kwargs)
    return _method

def mymethod(self, foo_ct):
    """ self is not bound because we aren't using object __new__
        you can write the __setattr__ method to bind a self 
        argument, or declare your functions dynamically to bind in 
        a static object reference.
    """
    return self.foo_str + foo_ct

setattr(myobj, 'foo', func_bind_obj_as_self(mymethod, myobj))

-2

Bu konuyu ölümden geri getireceğimi biliyorum, ancak bir mülkün sadece okunabilir hale getirilmesine bakıyordum ve bu konuyu bulduktan sonra, zaten paylaşılan çözümlerden memnun kalmadım.

Bu kodla başlarsanız, ilk soruya geri dönersek:

@property
def x(self):
    return self._x

Ve X'i salt okunur yapmak istiyorsanız, sadece şunları ekleyebilirsiniz:

@x.setter
def x(self, value):
    raise Exception("Member readonly")

Ardından, aşağıdakileri çalıştırırsanız:

print (x) # Will print whatever X value is
x = 3 # Will raise exception "Member readonly"

3
Ancak pasör yapmazsanız, atamaya çalışmak da bir hataya neden olur (An AttributeError('can't set attribute'))
Artyer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.