Вопрос по python – Объявление переменной Python

68

Изучает питон и имеет некоторые основные сомнения.

1.Я видел объявление переменной (путь здесь) как

class writer:
    path = ""

иногда нет явного объявления, но инициализируется через__init__.

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

Я понимаю цель__init__, но желательно ли объявлять переменную в любых других функциях.

2.Как я могу создать переменную для хранения пользовательского типа?

class writer:
    path = "" # string value
    customObj = ??
И, что касается второго вопроса: в Python переменные не имеют типа: значения имеют. Таким образом, любая переменная может содержать ваши пользовательские объекты. jpaugh
@gnibbler Или имена для них ... detly
Это поможет, если вы перестанете думать об именах / идедификаторах как оvariables, Они естьreferences к объектам John La Rooy
@ детально, я думаю, что имена - плохой выбор. Вещи обычно имеют только одно имя, тогда как объект может иметь несколько ссылок John La Rooy
@JohnClements, но python не работает как математика. Если вы хотите понять Python, вы должны знать, что объекты с__name__ Атрибут имеет «имя». Не все объекты имеют__name__ атрибут, но вы все равно можете иметь ссылки на них. Если мы начнем называть & quot; ссылку & quot; & quot; имя & quot; мы оказываем новичкам медвежью услугу в будущем. John La Rooy

Ваш Ответ

5   ответов
6

но в Python 3.5 и выше вы объявляете тип переменной следующим образом:

variable_name: type_name

или это:

variable_name # type: shinyType

Так что в вашем случае (если у вас естьCustomObject класс определен), вы можете сделать:

customObj: CustomObject

Увидетьэтот или жетот для получения дополнительной информации.

171

There is no such thing as "variable declaration" or "variable initialization" in Python.

Это просто то, что мы называем «назначение», но, вероятно, следует просто назвать «присвоение имен».

Назначение означает «это имя с левой стороны теперь относится к результату оценки с правой стороны, независимо от того, на что оно ссылалось ранее (если вообще что-либо)».

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

Как таковые, имена Python (термин лучше, чем «переменные», возможно) не имеют связанных типов; значения делают. Вы можете повторно применить одно и то же имя к чему угодно, независимо от его типа, но вещь все еще имеет поведение, которое зависит от ее типа. Имя - это просто способ ссылки на значение (объект). Это отвечает на ваш второй вопрос: выdon't создать переменные для хранения пользовательского типа. Вы не создаете переменные для хранения какого-либо определенного типа. Вы не создаете & quot; переменные вообще. Вы даете имена объектам.

Второй момент: Python следует очень простому правилу, когда дело доходит до классов, что на самом деле гораздо более согласованно, чем то, что делают языки, такие как Java, C ++ и C #:everything declared inside the class block is part of the class, Итак, функции (def) здесь написаны методы, то есть часть объекта класса (не хранятся для каждого экземпляра), как в Java, C ++ и C #; но другие имена здесьalso часть класса. Опять же, имена - это просто имена, и они не имеют связанных типов, иfunctions are objects too в Python. Таким образом:

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

Classes are objects tooв Python.

Итак, теперь мы создалиobject названныйExample, который представляет класс всех вещей, которыеExamples. Этот объект имеет два пользовательскихattributes (В C ++ «члены» в C #, «поля или свойства или методы»; в Java «поля или методы»). Один из них названdataи хранит целочисленное значение42, Другой названmethodи он хранит объект функции. (Есть еще несколько атрибутов, которые Python добавляет автоматически.)

Эти атрибуты все еще не являются частью объекта. По сути, объект - это просто набор из большего количества имен (имен атрибутов), пока вы не приступите к вещам, которые больше не могут быть разделены. Таким образом, значения могут быть разделены между различными экземплярами класса или даже между объектами разных классов, если вы намеренно настроили это.

Давайте создадим экземпляр:

x = Example()

Теперь у нас есть отдельный объект с именемx, который является примеромExample,data а такжеmethod на самом деле не являются частью объекта, но мы все еще можем искать их черезx из-за какой-то магии, которую Питон делает за кулисами. Когда мы смотримmethodв частности, вместо этого мы получим «связанный метод» (когда мы это называем,x передается автоматически какself параметр, который не может произойти, если мы посмотрим вверхExample.method напрямую).

Что происходит, когда мы пытаемся использоватьx.data?

Когда мы изучаем его, он сначала смотрит на объект. Если он не найден в объекте, Python просматривает класс.

Тем не менее, когда мыassign to x.data, Python создаст атрибут для объекта. Будетnot заменить класс & apos; приписывать.

Это позволяет нам делатьobject инициализация. Python автоматически вызовет класс & apos;__init__ метод для новых экземпляров, когда они созданы, если они есть. В этом методе мы можем просто назначить атрибутам установить начальные значения для этого атрибута для каждого объекта:

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

Теперь мы должны указатьname когда мы создаемExampleи каждый экземпляр имеет свойname, Python будет игнорировать атрибут классаExample.name всякий раз, когда мы смотрим.name экземпляра, потому что атрибут экземпляра будет найден первым.

Последнее предостережение:modification (mutation) and assignment are different things!

В Python строки неизменны. Они не могут быть изменены. Когда вы делаете:

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

Выdo not change оригинал "привет" строка. Это невозможно в Python. Вместо этого вы создаетеnew строка'hi mom'и причинаa перестать быть именем для'hi 'и начать быть именем для'hi mom' вместо. Мы сделалиb имя для'hi ' а также, и после повторного примененияa название,b все еще имя для'hi ', так как'hi ' все еще существует и не был изменен.

Но списки могут быть изменены:

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

Сейчасb [1, 2, 3, 4], потому что мы сделалиb имя для того же, чтоa по имени, а затем мы изменили эту вещь. Мы не создали новый список дляa назвать, потому что Python просто относится+= по-разному для списков.

Это имеет значение для объектов, потому что если у вас есть список в качестве атрибута класса и вы используете экземпляр для изменения списка, то это изменение будет "видно". во всех других случаях. Это потому, что (а) данные на самом деле являются частью объекта класса, а не какого-либо объекта экземпляра; (б) поскольку вы изменяли список и не выполняли простого назначения, вы не создали новый атрибут экземпляра, скрывающий атрибут класса.

Вот почему мы называем их'identifiers'. :-)
Объявление переменной хорошо объяснено в этом видео:youtube.com/watch?v=ao2N37E-D9s.
@Karl_Knechtel в вашем примере строки, в конце концов, что происходит с "привет"! если мы никогда не назовем его как «b»? Это утечка памяти?
@heretoinfinity: нет; Python использует сборку мусора для освобождения недоступных объектов
20

о переменных в функциях или модулях, объявление не требуется. Просто назначьте значение имени, где оно вам нужно:mymagic = "Magic", Переменные в Python могут содержать значения любого типа, и вы не можете их ограничивать.

Ваш вопрос, в частности, касается классов, объектов и переменных экземпляра. Идиоматический способ создания переменных экземпляра заключается в__init__ метод и больше нигде & # x2014; пока тыcould создавать новые переменные экземпляра в других методах или даже в несвязанном коде, это просто плохая идея. Это сделает ваш код трудным для рассуждения или поддержки.

Так, например:

class Thing(object):

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

Легко. Теперь экземпляры этого класса имеютmagic атрибут:

thingo = Thing("More magic")
# thingo.magic is now "More magic"

Создание переменных в пространстве имен самого класса приводит к совершенно другому поведению. Это функционально отличается, и вы должны делать это, только если у вас есть конкретные причины для этого. Например:

class Thing(object):

    magic = "Magic"

    def __init__(self):
        pass

Теперь попробуйте:

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

Или же:

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"]

Это связано с тем, что пространство имен самого класса отличается от пространства имен объектов, созданных из него. Я оставлю это вам, чтобы исследовать это немного подробнее.

Главная идея заключается в том, что идиоматический Python должен (а) инициализировать атрибуты объекта в вашем__init__ метод, и (б) документировать поведение вашего класса по мере необходимости. Вам не нужно вдаваться в подробности документации уровня Сфинкса для всего, что вы когда-либо пишете, но, по крайней мере, некоторые комментарии о любых деталях, которые вам или кому-то еще могут понадобиться, чтобы их найти.

1

поэтому да, уместно иметь переменные, которые являются специфическими для вашей функции. Вы не всегда должны четко указывать их определение; обычно вы можете просто использовать их. Только если вы хотите сделать что-то определенное для типа переменной, например добавить список, вам нужно определить их, прежде чем начать их использовать. Типичный пример этого.

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

Кстати, это не очень хороший способ настроить список. Было бы лучше сказать:

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

... но я отвлекся.

Ваш другой вопрос. Пользовательский объект должен быть самим классом.

class CustomObject(): # always capitalize the class name...this is not syntax, just style.
  pass
customObj = CustomObject()
6

custom_object = Нет

Похожие вопросы