#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
orChannel.channel_mapping
в том случае, когдаchannel_mapping
он доступен только для чтения. Это также означает, что он должен быть потокобезопасным.2. @quamrana, значит, мой channel_mapping доступен только для чтения, верно? Нет записи в него после его первоначального заполнения.
3. Классы не создают новую область видимости.
channel_mapping
не является глобальной переменной; это атрибут класса и, следовательно, доступен только через класс (или экземпляр класса).4.
channel_mapping
существует только послеdict
создания и заполнения ит-ссылок. Вы также должны убедиться, что вы никогда не записываете в него, чтобы сделать его доступным только для чтения. По совпадению, он по-прежнему доступен только для чтения.
Ответ №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, так и о переменной экземпляра, поскольку в вашем случае они одинаковы) изнутри или снаружи, тогда да, это будет потокобезопасно, поскольку нет никаких возможных задержек при обновлении переменных по мере необходимости.они вообще не будут обновляться.