Więc mam klasę z kilkoma metodami zdefiniowanymi jako:

class Recognizer(object):

    def __init__(self):
        self.image = None
        self.reduced_image = None

    def load_image(self, path):
        self.image = cv2.imread(path)
        return self.image

Powiedz, że chcę dodać trzecią metodę, która używa wartości powrotu od ładunku_image (). Powinienem go zdefiniować tak:

    def shrink_image(self):
        self.reduced_img = cv2.resize(self.image, (300, 300))
        return self.reduced_img

Czy powinienem go zdefiniować tak:

    def shrink_image(self, path):
        reduced_img = cv2.resize(self.load_image(path), (300, 300))
        return reduced_img

Co dokładnie jest różnica między nimi? Widzę, że mogę mieć dostęp do pól wewnątrz init z dowolnej metody, którą zadeklaruję w tej klasie, więc chyba, że gdy będę zaktualizować pola w init byłbym w stanie uzyskać dostęp do tych pól na przykład w danym czasie. Czy istnieje konsensus, w jaki sposób jest lepszy?

3
dikshant 12 październik 2017, 14:55

2 odpowiedzi

Najlepsza odpowiedź

Co dokładnie jest różnica między nimi?

W Pythonie funkcja z podpisem __init__ jest konstruktorem obiektu, który jest wywoływany domyślnie podczas dzwonienia go za pomocą (), takimi jak rozpoznawnik ()

Termin "lepszy" jest niejasny, ponieważ w dawnym przykładzie zapisujesz obraz jako nieruchomość na obiekcie, stąd obiekt większy.

Ale w drugim przykładzie po prostu zwracasz dane z funkcji, do użycia przez dzwoniącego.

Więc to kwestia kontekstu i stylu.

Prosta reguła kciuka jest, jeśli będziesz korzystać z właściwości Rude_img w kontekście obiektu rozpoznawczego, idealny byłoby, aby zapisać go jako nieruchomość na obiekcie, do uzyskania dostępu samego siebie. Jeśli dzwoniący po prostu używa Rude_img i rozpoznawania jest nieświadomy jakichkolwiek zmian stanu, to dobrze jest zwrócić go z funkcji.

1
Ólafur Aron 12 październik 2017, 13:56

W drugim sposobie zmienna jest zasłoniona do funkcji shrink_image.

W pierwszej okolicy zmienna jest zasłoniona do życia obiektów, a mający zestaw self.reduced_img jest a Efekt uboczny metody.

Widząc tylko próbkę kodu, bez widzenia klientów, drugi przypadek jest "lepszy", ponieważ {x0}} nie jest używany nigdzie indziej i jest nieufny, aby wiązać go w instancji. Tam może być przypadek użycia, w którym musisz utrzymywać ostatnie self.reduced_img połączenie, dzięki czemu jest to niezbędny efekt uboczny.

Ogólnie rzecz biorąc niezwykle pomocne, aby zminimalizować skutki uboczne. Posiadanie skutków ubocznych, szczególnie te, które mutate stan może sprawić, że rozumowanie programu jest trudniejsze.

Jest to szczególnie widoczne, gdy masz wielu akcesoriów do obiektu.

Wyobraź sobie, że masz pierwsze shrink_image, publikujesz swój program, masz jednego klienta w jednym połączeniu programu wywołania shrink_object, łatwe peady. Po połączeniu self.reduced_img będzie wynikiem.

Wyobraź sobie udostępnianie obiektu między wieloma stronami połączeń? Wprowadza sprzężenie tymczasowe ish: nie możesz już być w stanie założyć założenie o tym, co jest reduced_img. Może być innymi dzwoniącymi !!!

Porównaj to z drugim skurczowym obrazem, rozmówcy nie mają już mrukowanego stanu, a łatwiej jest rozumować stan Recognizer instancji shrink_image połączenia.


Coś naprawdę się dzieje na pierwszym przykładzie, gdy wprowadzono wiele połączeń jednoosobowych. Jest to trudne do rozumowania i potencjalnie logicznie nieprawidłowo, by być synchronizacją i kwestią rasy danych.

Bez współbieżnych dzwoniących to nie będzie problemem. Ale jest to możliwość, jeśli używasz tego połączenia w ramach internetowych i tworzysz jedną instancję do udostępniania wielu procesów pracowników internetowych, możesz uzyskać tę ukryte współbieżność i potencjalnie może podlegać warunkach wyścigu: P

1
dm03514 12 październik 2017, 13:47