Для начала я переименовываю UserClass
в User
(мы знаем, что это класс) и UserID
в id
(это класс User
, поэтому нет необходимости повторять бит «Пользователь», а стиль Python рекомендует строчные буквы) и __user_id_counter
в __id_counter
(то же самое). Прочтите PEP 8, чтобы ознакомиться с рекомендациями по стилю Python.
Итак, наша отправная точка такова:
class User(object):
__id_counter = 0
def __init__(self, id=None) :
self.id = self.__id_counter if id is None else id
__id_counter += 1
myuser = User()
myuser2 = User()
myuser3 = User()
Теперь двойное подчеркивание в начале (без двойного подчеркивания в конце, как в таких вещах, как __init__
и __metaclass__
) является особенным и используется для реализации частных переменных класса — читайте о частные переменные в руководстве по Python для получения дополнительной информации. Это вызывает так называемое «искажение имени». Что это заканчивается, так это то, что __id_counter
переименовывается в _User__id_counter
по всему классу. Это и полезно, и опасно. В данном случае, я думаю, это, вероятно, просто не нужно.
Это может привести к проблемам с подклассами.
class SpecialUser(User):
def __init__(self):
self.__id_counter
Теперь SpecialUser()
вызовет AttributeError: 'SpecialUser' object has no attribute '_SpecialUser__id_counter'
.
Итак, вопрос в том, хотите ли вы, чтобы подклассы имели один и тот же счетчик ID или свои собственные счетчики ID?
Если вы хотите, чтобы у них был одинаковый счетчик ID, используйте User.__id_counter
. Не используйте self.__class__.__id_counter
или type(self).__id_counter
с += 1
, так как это для экземпляра SpecialUser
установит SpecialUser._User__id_counter
на User._User__id_counter + 1
, а затем SpecialUser
будет использовать собственный _User__id_counter
с этой точки вперед, что далеко от того, что вы хотите.
Если вы хотите, чтобы у них были собственные счетчики идентификаторов, начните с использования _id_counter
, а не __id_counter
, так как искажение имени приведет вас в нежелательном направлении.
Есть несколько подходов, которые вы можете предпринять:
Используйте метакласс, чтобы дать каждому классу свою собственную переменную-счетчик (более сложная тема, чем я могу писать о ней в данный момент, запросите более подробную информацию, если хотите).
Вставьте строку _id_counter = 0
в каждое определение класса. (Если вы этого не сделаете, у вас возникнут проблемы с отправной точкой идентификатора — сделайте их много, например, User(), User(), SpecialUser(), User(), SpecialUser(), SpecialUser(), User()
, и они будут иметь идентификаторы (соответственно) 0, 1, 2, 2, 3, 4, 3
, а не 0, 1, 0, 2, 1, 2
.
Дополнительная неэффективность, которая может возникнуть из-за использования здесь подхода с изменением имени, заключается в том, что подклассы будут иметь несколько счетчиков в них - _User__id_counter
, _SpecialUser__id_counter
и т. д.
person
Chris Morgan
schedule
27.07.2011