Подтвердить что ты не робот

Объявление переменной Python

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

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

class writer:
    path = ""

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

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

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

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

class writer:
    path = "" # string value
    customObj = ??
4b9b3361

Ответ 1

Хорошо, сначала сначала.

В 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 (лучший термин, чем "переменные", возможно) не имеют связанных типов; значения делают. Вы можете повторно применить одно и то же имя к чему бы то ни было, независимо от его типа, но все еще имеет поведение, зависящее от его типа. Имя - это просто способ ссылаться на значение (объект). Это отвечает на ваш второй вопрос: вы не создаете переменные для хранения пользовательского типа. Вы не создаете переменные для хранения какого-либо определенного типа. Вы вообще не создаете переменные. Вы даете имена объектам.

Вторая точка: Python следует очень простому правилу, когда дело доходит до классов, что на самом деле гораздо более согласовано, чем такие языки, как Java, С++ и С#: все, объявленное внутри блока class, является частью класс. Таким образом, функции (def), написанные здесь, - это методы, то есть часть объекта класса (не хранящиеся на основе каждого экземпляра), как и в Java, С++ и С#; но другие имена здесь также часть класса. Опять же, имена - это просто имена, и у них нет связанных типов, а - объекты тоже в Python. Таким образом:

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

Классы также являются объектами, в Python.

Итак, теперь мы создали объект с именем Example, который представляет класс всех вещей Example s. Этот объект имеет два атрибута для пользователя (в С++, "члены", в С#, "поля или свойства или методы", в Java "поля или методы" ). Один из них называется data, и он сохраняет целочисленное значение 42. Другой - method, и он сохраняет объект функции. (Есть еще несколько атрибутов, которые автоматически добавляет Python.)

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

Позвольте создать экземпляр:

x = Example()

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

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

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

Однако, когда мы назначаем x.data, Python создаст атрибут объекта. Это заменит атрибут не.

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

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

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

Последнее предупреждение: модификация (мутация) и назначение - это разные вещи!

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

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

Вы не меняете исходную строку "привет". Это невозможно в 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 просто обрабатывает += по-разному для списков.

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

Ответ 2

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

Однако ваш вопрос задает вопрос о классах, объектах и ​​переменных экземпляра. Идиоматический способ создания переменных экземпляра находится в методе __init__ и нигде больше - в то время как вы могли бы создавать новые переменные экземпляра в других методах или даже в неродственном коде, это просто плохая идея. Это сделает ваш код трудно обосновать или поддерживать.

Итак, например:

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__ и (b) документировать поведение вашего класса по мере необходимости. Вам не нужно беспокоиться о полномасштабной документации на уровне Sphinx для всего, что вы когда-либо пишете, но, по крайней мере, некоторые комментарии о любых деталях, которые вам или кому-то еще могут понадобиться, чтобы поднять их.

Ответ 3

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

variable_name: type_name

или это:

variable_name # type: shinyType

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

customObj: CustomObject

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

Ответ 4

Для определения области применения я использую:

custom_object = None

Ответ 5

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

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()