Deklaracja Zmiennych Pythona

Nauka Python {[7] } i ma podstawowe wątpliwości.

1.I have seen variable declaration (path here) as

class writer:
    path = ""

Czasami nie ma wyraźnej deklaracji, ale inicjalizuje się przez __init__.

def __init__(self, name):
    self.name = name

Rozumiem cel __init__, ale czy warto deklarować zmienną w innych funkcjach.

2.Jak mogę utworzyć zmienną do przechowywania niestandardowego typu?

class writer:
    path = "" # string value
    customObj = ??
Author: Zach, 2012-06-13

5 answers

Po kolei.

Nie ma czegoś takiego jak "deklaracja zmiennej" lub "inicjalizacja zmiennej" w Pythonie.

Jest po prostu to, co nazywamy "przypisaniem", ale prawdopodobnie powinniśmy po prostu nazwać "nazewnictwem".

Przypisanie oznacza " ta nazwa po lewej stronie odnosi się teraz do wyniku oceny prawej strony, niezależnie od tego, do czego się wcześniej odnosiła (jeśli w ogóle)".

foo = 'bar' # the name 'foo' is now a name for the string 'bar'
foo = 2 * 3 # the name 'foo' stops being a name for the string 'bar',
# and starts being a name for the integer 6, resulting from the multiplication

Jako takie, nazwy Pythona (lepsze określenie niż "zmienne", prawdopodobnie) nie mają powiązanych typów; wartości tak. Możesz ponownie zastosować tę samą nazwę do wszystkiego, niezależnie od jego typu, ale rzecz nadal ma zachowanie, które zależy od jej typu. Nazwa jest po prostu sposobem odniesienia się do wartości (obiektu). To odpowiada na drugie pytanie: ty Nie twórz zmienne, aby trzymać niestandardowy typ. Nie tworzy się zmiennych do przechowywania określonego typu. W ogóle nie" tworzysz " zmiennych. Nadajesz nazwy przedmiotom.

Drugi punkt: Python przestrzega bardzo prostej zasady, jeśli chodzi o klasy, która jest o wiele bardziej spójna niż języki takie jak Java, C++ i C#: Wszystko zadeklarowane wewnątrz class bloku jest częścią klasy. Tak więc, funkcje (def) napisane tutaj są metodami, tzn. częścią obiektu klasy (nie przechowywanego na zasadzie instancji), tak jak w Javie, C++ i C#; ale inne nazwy tutaj są również częścią klasy. Znowu imiona to tylko imiona i nie mają typy powiązane i funkcje są również obiektami w Pythonie. Tak więc:

class Example:
    data = 42
    def method(self): pass

Klasy są również obiektami w Pythonie.

Więc teraz stworzyliśmy obiekt o nazwie Example, który reprezentuje klasę wszystkich rzeczy, które są Example s. obiekt ten ma dwa atrybuty dostarczone przez użytkownika (W C++ "członkowie"; w C# "pola lub Właściwości lub metody"; w Javie "pola lub metody"). Jeden z nich ma nazwę data i przechowuje wartość całkowitą 42. Na Inne ma nazwę method i przechowuje obiekt funkcji. (Istnieje jeszcze kilka atrybutów, które Python dodaje automatycznie.)

Te atrybuty nadal nie są częścią obiektu. Zasadniczo obiekt jest tylko pakietem większej liczby nazw (nazw atrybutów), dopóki nie przejdziesz do rzeczy, których nie można już podzielić. W ten sposób wartości mogą być współdzielone między różnymi instancjami klasy, a nawet między obiektami różnych klas, jeśli celowo ustawisz, że w górę.

Stwórzmy instancję:

x = Example()

Teraz mamy oddzielny obiekt o nazwie x, który jest instancją Example. data i method nie są w rzeczywistości częścią obiektu, ale nadal możemy je sprawdzić poprzez x z powodu jakiejś magii, którą Python robi za kulisami. Gdy spojrzymy w górę method, w szczególności, zamiast tego otrzymamy "bound method" (kiedy ją wywołamy, {[13] } jest przekazywana automatycznie jako parametr self, co nie może się zdarzyć, jeśli spojrzymy w górę Example.method bezpośrednio).

Co się dzieje, gdy próbujemy użyć x.data?

Kiedy go zbadamy, najpierw znajduje się w obiekcie. Jeśli nie znajduje się w obiekcie, Python zagląda do klasy.

Jednakże, gdy przypisujemy do x.data, Python utworzy atrybut na obiekcie. To Nie zastąpi atrybut klasy.

To pozwala nam na inicjalizację obiektu . Python automatycznie wywoła metodę class ' __init__ na nowych instancjach kiedy są tworzone, jeśli są obecne. W tej metodzie możemy po prostu przypisać do atrybutów, aby ustawić początkowe wartości dla tego atrybutu na każdym obiekcie:

class Example:
    name = "Ignored"
    def __init__(self, name):
        self.name = name
    # rest as before

Teraz musimy określić name Kiedy tworzymy Example, a każda instancja ma swój własny name. Python zignoruje atrybut klasy Example.name za każdym razem, gdy spojrzymy na .name instancji, ponieważ atrybut instancji zostanie znaleziony jako pierwszy.

Ostatnie zastrzeżenie: modyfikacja (mutacja) i przypisanie są różne rzeczy!

W Pythonie ciągi są niezmienne. Nie można ich modyfikować. Kiedy robisz:

a = 'hi '
b = a
a += 'mom'

Ty nie zmieniaj oryginalnego ciągu 'cześć'. To niemożliwe w Pythonie. Zamiast tego tworzysz nowy ciąg znaków 'hi mom' i sprawiasz, że a przestaje być nazwą dla 'hi ', a zamiast tego zaczynasz być nazwą dla 'hi mom'. Stworzyliśmy b nazwę dla 'hi ', a po ponownym zastosowaniu nazwy a, b nadal jest nazwą dla 'hi ', ponieważ 'hi ' nadal istnieje i nie został zmieniony.

Ale listy można zmienić:

a = [1, 2, 3]
b = a
a += [4]

Teraz b jest również [1, 2, 3, 4], ponieważ stworzyliśmy b nazwę dla tej samej rzeczy, którą nazwaliśmy {31]}, a potem zmieniliśmy tę rzecz. Nie stworzyliśmy nowej listy dla a, ponieważ Python po prostu traktuje += inaczej dla list.

Ma to znaczenie dla obiektów, ponieważ jeśli masz listę jako atrybut klasy i używasz instancji do modyfikowania listy, to zmiana będzie "widoczna" we wszystkich inne przypadki. Dzieje się tak dlatego, że (a) dane są rzeczywiście częścią obiektu klasy, a nie jakiegokolwiek obiektu instancji; (b) ponieważ modyfikowałeś listę i nie wykonywałeś prostego przypisania, nie utworzyłeś nowego atrybutu instancji ukrywającego atrybut klasy.

 207
Author: Karl Knechtel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-13 04:43:20

Może to być 6 lat spóźnione, ale w Pythonie 3.5 i nowszych, deklarujesz typ zmiennej taki jak:

variable_name: type_name

Lub to:

variable_name # type: shinyType

Więc w Twoim przypadku (jeśli masz zdefiniowaną klasę CustomObject), możesz zrobić:

customObj: CustomObject
Zobacz tolub tamtoaby uzyskać więcej informacji.
 23
Author: O. Aroesti,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-04 14:35:18

Nie ma potrzeby deklarowania nowych zmiennych w Pythonie. Jeśli mówimy o zmiennych w funkcjach lub modułach, nie jest potrzebna żadna deklaracja. Po prostu przypisz wartość do nazwy tam, gdzie jej potrzebujesz: mymagic = "Magic". Zmienne w Pythonie mogą zawierać wartości dowolnego typu i nie można tego ograniczyć.

Twoje pytanie dotyczy klas, obiektów i zmiennych instancji. Idiomatyczny sposób tworzenia zmiennych instancji jest w metodzie __init__ i nigdzie indziej - podczas gdy można utworzyć nowe zmienne instancji w innych metodach, a nawet w niezwiązanym kodzie, to po prostu zły pomysł. To sprawi, że Twój kod będzie trudny do rozumowania lub utrzymania.

Więc na przykład:

class Thing(object):

    def __init__(self, magic):
        self.magic = magic
Spokojnie. Teraz instancje tej klasy mają atrybut magic:
thingo = Thing("More magic")
# thingo.magic is now "More magic"

Tworzenie zmiennych w przestrzeni nazw samej klasy prowadzi do zupełnie innego zachowania. Jest funkcjonalnie inny i powinieneś to robić tylko wtedy, gdy masz konkretny powód. Na przykład:

class Thing(object):

    magic = "Magic"

    def __init__(self):
        pass

Teraz try:

thingo = Thing()
Thing.magic = 1
# thingo.magic is now 1

Lub:

class Thing(object):

    magic = ["More", "magic"]

    def __init__(self):
        pass

thing1 = Thing()
thing2 = Thing()
thing1.magic.append("here")
# thing1.magic AND thing2.magic is now ["More", "magic", "here"]

Dzieje się tak dlatego, że przestrzeń nazw samej klasy różni się od przestrzeni nazw obiektów z niej utworzonych. Zostawię ci to, abyś zbadał to trochę więcej.

Komunikat take-home jest taki, że Python idiomatyczny ma (a) zainicjalizować atrybuty obiektu w Twojej metodzie __init__ i (b) udokumentować zachowanie twojej klasy w razie potrzeby. Nie musisz zadawać sobie trudu z pełną dokumentacją na poziomie Sphinx dla wszystkiego, co kiedykolwiek piszesz, ale przynajmniej kilka komentarzy na temat jakichkolwiek szczegółów, które ty lub ktoś inny może potrzebować, aby je odebrać.

 22
Author: detly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-13 03:38:41

W celu określenia zakresu używam:

custom_object = None
 14
Author: redhot,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-30 10:31:56

Zmienne mają zakres, więc tak, właściwe jest posiadanie zmiennych specyficznych dla twojej funkcji. Nie zawsze musisz być jednoznaczny co do ich definicji; zazwyczaj możesz po prostu ich użyć. Tylko jeśli chcesz zrobić coś specyficznego dla typu zmiennej, np. dodać listę, musisz je zdefiniować, zanim zaczniesz ich używać. Typowy przykład tego.

list = []
for i in stuff:
  list.append(i)

Przy okazji, to nie jest dobry sposób na ustawienie listy. Byłoby lepiej powiedz:

list = [i for i in stuff] # list comprehension

...ale dygresję.

Twoje drugie pytanie. Obiekt niestandardowy powinien być klasą samą w sobie.
class CustomObject(): # always capitalize the class name...this is not syntax, just style.
  pass
customObj = CustomObject()
 2
Author: ChipJust,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-13 03:12:16