ograniczenie dostępu do zmiennych w klasie a interfejsy

Odpowiedz Nowy wątek
2019-03-04 17:52
0

Witajcie.

Załóżmy, że mam prostą klasę, w której mam potrzebę kontroli tego, co jest w jej instancji przypisywane, tak więc tworzę kod z definicją slots:

class Test:
    __slots__ = ['_out']
    def __init__(self):
        self._out = None
        pass

    @property
    def out(self):
        return self._out

    @out.setter
    def out(self, value):
        self._out = value

if __name__ == "__main__":
    o = Test()
    o.out = "test"
    o._x = 'a'
    print("{}".format(o))
    print("OUT: {}".format(o.out))

Rzuca to wyjątek zgodnie z moimi oczekiwaniami:

% python3 test.py
Traceback (most recent call last):
  File "test.py", line 32, in <module>
    o._x = 'a'
AttributeError: 'Test' object has no attribute '_x'

Załóżmy jednak potrzebę utworzenia interfejsu, z której powyższa klasa będzie dziedziczyła:

from abc import ABC, abstractmethod

class ITest(ABC):
    @property   
    @abstractmethod
    def out(self):
        pass

    @out.setter
    @abstractmethod
    def out(self):
        pass

class Test(ITest):
    __slots__ = ['_out']
[dalej bez zmian]

w powyższej sytuacji deklaracja slots nie ogranicza już możliwości tworzenia atrybutów:

% python3 test.py
<__main__.Test object at 0x7f5347a40248>
OUT: test

I tutaj moje pytanie: jak to poprawnie napisać przy powyższych założeniach?

Mamy założyć że zaimportowane ABC to class Test z pierwszego wklejonego kodu? Drugie pytanie, próbowałeś nadpisać metodę __setattr__? Oczywiście to i tak ci niczego nie zagwarantuje, ponieważ odpowiednie nadpisanie z poziomu klasy dziedziczącej i tak da komuś dostęp, jednak można go utrudnić na wiele sposobów :). - Guaz 2019-03-04 18:42
W Pythonie nie zakłada się klatek erekcyjnych. Takie rzeczy to u dewiantów w Dżawie i C#. - Mózg 2019-03-04 19:17
@Mózg podpisuje się. Chociaż jeszcze z zabezpieczeniem zmiennej by była readonly aby jej przypadkiem nie zmienić, to się spotkałem. (Przy implementacjach modułów z innych języków) ale to by było tyle w tej kwestii. Da się namotać w kodzie by nie dało się dobrać do zmiennych w pewnym stopniu, ale skuteczny 'override' gdy ktoś wie co robi, i tak ci zepsuje 'głupi pomysł'. Zawsze się możesz dobrać do atrybutów. - Guaz 2019-03-04 20:39

Pozostało 580 znaków

2019-03-05 09:43
1

Możesz cudować ze slots czy setattr ale czy jest sens? Przeciwko komu chcesz to napisać? Bo to Python, tutaj zawsze da się to obejść, co byś tam nie zrobił.


Na PW przyjmuje tylko (ciekawe!) zlecenia. Masz problem? Pisz na forum, nie do mnie.

Pozostało 580 znaków

2019-03-05 11:17
0

Przecież abc to standardowy moduł Pythona: Abstract Base Classes, w każdym razie serdeczne dzięki za naprowadzenie, użyłem __setattr__ i metaclass. Działa poprawnie poza klasami dziedziczonymi z Thread ale z tym sobie poradzę.
Piszę to wyłącznie przeciwko sobie, by chronić dodatkowo pisany kod przed błędami, które ciężko jest mi debugować testami jednostkowymi. Powstaje dosyć złożona aplikacja sieciowa w której napisanie poprawnych unittestów w dynamicznie zmieniającym się środowisku jest dla mnie sporym wyzwaniem.

Pozostało 580 znaków

2019-03-05 12:05
0

To może lepiej użyć typecheckera? :) Nadwaj explicite typy i dostaniesz informacje kiedy odniesiesz sie do pola którego dany typ nie ma.


Na PW przyjmuje tylko (ciekawe!) zlecenia. Masz problem? Pisz na forum, nie do mnie.

Pozostało 580 znaków

2019-03-05 12:34
0

Dzięki, obadam temat.

Zdecydowanie w tym celu co napisałeś, obadaj nim zabrniesz za daleko w ograniczanie siebie - co skutkuje stratą czasu i wyprodukowaniem dziwnego tworu (kod działający w pythonie, nie zachowujący się jak python). Tak się w pythonie lepiej dba o takie rzeczy :) - Guaz 2019-03-05 18:29

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0