Почему мне нужно использовать «self» для ссылки на переменную класса в методе класса?

#python

#питон

Вопрос:

 class Channel(object)
  channel_mapping = {
    'a': 001,
    'b': 002,
    'c': 003
  }

  def __init__(self):
    ...

  def process(self, input):
    channels = input.split(',')
    for channel in channels:
       if channel in self.channel_mapping:
          channel = self.channel_mapping[channel]
          break
     ...
 

Я определил channel_mapping как переменную класса, и почему мне нужно использовать self для ссылки на нее? Я подумал, что мне следует просто использовать channel_mapping or cls.channel_mapping в process() функции.

Кроме того, чтобы определить channel_mapping как переменную класса, подобную этой, или определить ее как переменную экземпляра в инициализаторе, есть ли какие-либо проблемы с безопасностью потоков в любом случае?

Комментарии:

1. Вы можете использовать self.channel_mapping or Channel.channel_mapping в том случае, когда channel_mapping он доступен только для чтения. Это также означает, что он должен быть потокобезопасным.

2. @quamrana, значит, мой channel_mapping доступен только для чтения, верно? Нет записи в него после его первоначального заполнения.

3. Классы не создают новую область видимости. channel_mapping не является глобальной переменной; это атрибут класса и, следовательно, доступен только через класс (или экземпляр класса).

4. channel_mapping существует только после dict создания и заполнения ит-ссылок. Вы также должны убедиться, что вы никогда не записываете в него, чтобы сделать его доступным только для чтения. По совпадению, он по-прежнему доступен только для чтения.

5. это может помочь

Ответ №1:

Я определил ‘channel_mapping’ как переменную класса, и почему мне нужно использовать ‘self’ для ссылки на нее?

Вы можете ссылаться на переменную класса через self (если вы убедитесь, что она доступна только для чтения) и cls внутри класса, и его методы, и через объект classes или экземпляры извне класса.

В чем разница между использованием cls и self ? cls используется в classmethod, поскольку они не требуют инициализации и, следовательно, экземпляра объекта, и self используется внутри методов, для которых требуются экземпляры объекта.

Я подумал, что должен просто использовать ‘channel_mapping’

Области видимости внутри python не работают, как, например, в C #, где вы можете вызвать переменную класса, просто написав ее имя, опустив this там, где оно избыточно. В Python вы должны использовать self для ссылки на переменную экземпляра. То же самое относится и к переменным класса, но cls вместо (или self ) .

Если вы ссылаетесь channel_mapping , вы просто ссылаетесь на переменную из текущей или глобальной областей, независимо от того, существует она или нет, а не из класса или его экземпляра.

или cls.channel_mapping в функции ‘process’?

Из методов класса, которые вы наверняка хотели бы использовать cls.channel_mapping , поскольку cls представляют объект класса. Но из методов экземпляра, где вместо cls you есть self , вы можете ссылаться на переменную класса с помощью self.__class__.channel_mapping . Что он делает, так это просто возвращает класс экземпляра, который равен cls , и после этого вызывает переменную класса channel_mapping .

self.channel_mapping хотя это вернет тот же результат, но только потому, что в вашем коде не вызывается атрибут экземпляра channel_mapping , и поэтому python может разрешить вашу ссылку на переменную класса. Но если внутри экземпляра будет channel_mapping переменная, она больше не будет связана с исходными переменными класса, поэтому в этом случае вы хотели бы сохранить channel_mapping доступ только для чтения.

Подводя итог, чтобы ссылаться на переменную класса из метода класса, вы хотели бы просто использовать a cls , а для ссылки на переменную класса из метода экземпляра вам лучше использовать self.__class__.var конструкцию вместо self.var единицы.

Кроме того, чтобы определить ‘channel_mapping’ как переменную класса, подобную этой, или определить ее как переменную экземпляра в инициализаторе, есть ли какие-либо проблемы с безопасностью потоков в любом случае?

Бывают ситуации, когда вы хотите изменить переменные во всех экземплярах одновременно, и именно тогда переменные класса пригодятся, вам не нужно будет обновлять каждую ответственную переменную экземпляра в каждом экземпляре, вы просто обновите переменную класса и все.

Но, говоря о безопасности потоков, я не совсем уверен, будет ли он обновляться одновременно в каждом потоке или нет, но self.__class__ вернет обновленную версию класса a, как только он будет обновлен, поэтому self.__class__ переменные будут обновляться каждый раз, когда вы вызываете его, минимизируя период, в течение которого разные потоки будут использовать разные значения класса.та же переменная.

Однако обновление инициализированной переменной займет больше времени, если имеется более одного экземпляра, поэтому я бы счел ее менее потокобезопасной.

Комментарии:

1. В моем коде нет обновления для channel_mapping dict каким-либо методом, поэтому он должен быть потокобезопасным. Верно?

2. @marlon конечно, если у вас нет никаких намерений каким-либо образом изменить channel_mapping (я говорю как о классе one, так и о переменной экземпляра, поскольку в вашем случае они одинаковы) изнутри или снаружи, тогда да, это будет потокобезопасно, поскольку нет никаких возможных задержек при обновлении переменных по мере необходимости.они вообще не будут обновляться.