Python: специальные (статические и др.) члены класса

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Python: специальные (статические и др.) члены класса

Непрочитанное сообщение Olej » 02 фев 2019, 11:39

Иногда возникает такая необходимость ... статические методы или статические поля данных.
Очень полезная в том смысле статья Программирование на Python. Часть 7: Специальные методы и атрибуты классов
Статический метод может быть определен и внутри класса — для этого используется ключевое слово staticmethod, причем метод может быть вызван как статически, так и через инстанс:

Код: Выделить всё

class Multi:
    def imeth(self, x):
        print self, x
    def smeth(x):
        print x
    def cmeth(cls, x):
        print cls, x
    smeth = staticmethod(smeth)
    cmeth = classmethod(cmeth)

Код: Выделить всё

>>> Multi.smeth(3)    
3
>>> obj=Multi()
>>> obj.smeth(5)
5

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python: специальные (статические и др.) члены класса

Непрочитанное сообщение Olej » 02 фев 2019, 11:50

Остальные статьи этого цикла гораздо менее интересные ... за исключением, разве, предыдущей Программирование на Python: Часть 6. Классы
Атрибут данных можно сделать приватным (private) — т.е. недоступным снаружи — для этого слева нужно поставить два символа подчеркивания:

Код: Выделить всё

class Simple:
 u'Простой класс с приватным атрибутом'
 __private_attr = 10 
 def __init__(self, count, str):
 self.__private_attr = 20
 print self.__private_attr

Код: Выделить всё

s = Simple(1,'22')
print s.__private_attr
Последняя строка вызовет исключение — атрибут __private_attr годен только для внутреннего использования.

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python: специальные (статические и др.) члены класса

Непрочитанное сообщение Olej » 02 фев 2019, 12:22

Про статические переменные класса понаписано много, например, Static class variables in Python или Статические переменные класса в Python
Статическая переменная - это переменная, которая была распределена статически, что означает, что ее время жизни - это весь запуск программы. Статические переменные существуют только в одном экземпляре для каждого класса и не создаются.
В Python переменные, объявленные внутри определения класса, но не внутри метода, являются переменными класса или статики.
Но тут всё не так просто:

Код: Выделить всё

#!/usr/bin/python3 

class Spam1:
    counter = 0
    def __init__( self ):
        self.counter += 1
        print( self.counter ) 
    def get( self ):
        return self.counter

print( Spam1.counter )
a1 = Spam1()
a2 = Spam1()
a3 = Spam1()
print( Spam1.counter )

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/python$ ./stat1.py
0
1
1
1
0
Это очевидно не то, что мы желали получить ... по крайней мере, по аналогии с C/C++ ...
По времени жизни это переменная класса, вызываемая как Spam1.counter, ранее создания 1-го объекта класса, но это не сохраняющая значение между вызовами переменная, статическая.
Вложения
stat1.py
(220 байт) 111 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python: специальные (статические и др.) члены класса

Непрочитанное сообщение Olej » 02 фев 2019, 12:24

Olej писал(а): Это очевидно не то, что мы желали получить ... по крайней мере, по аналогии с C/C++ ...
По времени жизни это переменная класса, вызываемая как Spam1.counter, ранее создания 1-го объекта класса, но это не сохраняющая значение между вызовами переменная, статическая.
А теперь вот так, минимальным изменением одного единственного оператора:

Код: Выделить всё

#!/usr/bin/python3 

class Spam1:
    counter = 0
    def __init__( self ):
        Spam1.counter += 1
        print( self.counter ) 
    def get( self ):
        return self.counter

print( Spam1.counter )
a1 = Spam1()
a2 = Spam1()
a3 = Spam1()
print( Spam1.counter )

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/python$ ./stat2.py
0
1
2
3
3
P.S. И это не касается разницы Python 2 или 3, меня интересовал 3, но можете проверить в 2 и убедиться.
Вложения
stat2.py
(221 байт) 112 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python: специальные (статические и др.) члены класса

Непрочитанное сообщение Olej » 02 фев 2019, 12:38

Olej писал(а):
Статическая переменная - это переменная, которая была распределена статически, что означает, что ее время жизни - это весь запуск программы. Статические переменные существуют только в одном экземпляре для каждого класса и не создаются.
В Python переменные, объявленные внутри определения класса, но не внутри метода, являются переменными класса или статики.
Переделаю минимально 1-й пример:

Код: Выделить всё

#!/usr/bin/python3 

class Spam1:
    counter = 0
    def __init__( self ):
        self.counter += 1
    def get( self ):
        return self.counter

print( Spam1.__dict__ )
a1 = Spam1()
print( a1.__dict__ )

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/python$ ./stat3.py
{'__module__': '__main__', 'counter': 0, '__init__': <function Spam1.__init__ at 0x7f49ac954d08>, 'get': <function Spam1.get at 0x7f49ac9546a8>, '__dict__': <attribute '__dict__' of 'Spam1' objects>, '__weakref__': <attribute '__weakref__' of 'Spam1' objects>, '__doc__': None}
{'counter': 1}
Это 2 совершенно разных переменных с одним именем counter: а). переменная класса (статическая) и б). переменная объекта данных.
И теперь всё становится на свои места.
Вложения
stat3.py
(164 байт) 115 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python: специальные (статические и др.) члены класса

Непрочитанное сообщение Olej » 02 фев 2019, 12:54

Olej писал(а):
Статический метод может быть определен и внутри класса — для этого используется ключевое слово staticmethod, причем метод может быть вызван как статически, так и через инстанс:
И, наконец, относительно методов класса, ... можно и так:

Код: Выделить всё

#!/usr/bin/python3 

class Spam1:
    __counter = 0
    def __init__( self ):
        Spam1.__counter += 1
        self.__counter = Spam1.__counter 
    def get_ins( self ):
        return self.__counter
    def get_sum():
        return Spam1.__counter

a1 = Spam1()
a2 = Spam1()
a3 = Spam1()
print( a1.get_ins() )
print( Spam1.get_sum() )

Код: Выделить всё

olej@ACER:~/2019_WORK/own.WORK/python$ ./stat4.py
1
3
get_ins() - метод объекта - номер конкретного инстанса;
get_sum() - метод класса - число созданных объектов вообще;

Аватара пользователя
Olej
Писатель
Сообщения: 21336
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Python: специальные (статические и др.) члены класса

Непрочитанное сообщение Olej » 04 май 2019, 10:04

Ещё раз убедился насколько полезная именно эта статья, о специальных возможностях классов, зачастую скрытых ... эти возможности очень скудно упоминаются даже в справочниках по Python - относятся больше к вопросам внутренней реализации:
Содержание
Введение
1. Объекты классов и специальные методы
2. Экземпляры классов и специальные методы
3. Экземпляры классов в качестве последовательностей
4. Приведение объектов к базовым типам
5. Bound и unbound методы
6. Метод super
7. Статические методы
8. Итератор
9. Property
10. Singleton
11. Слоты
12. Функтор
13. Дескриптор
14. Sequence
Но именно из-за того, что это уже на грани внутренней реализации, здесь можно легко напороться на различия Python 2 и 3. Авторская статься написана применительно к 2.6. Но это легко проверить и распространить на Python 3, сделав это непосредственно при написании собственного кода.


Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 9 гостей