Is it possible to have static class variables or methods in python? What syntax is required to do this?
相关问题
- how to define constructor for Python's new Nam
- streaming md5sum of contents of a large remote tar
- How to get the background from multiple images by
- Evil ctypes hack in python
- Correctly parse PDF paragraphs with Python
Static and Class Methods
As the other answers have noted, static and class methods are easily accomplished using the built-in decorators:
As usual, the first argument to
MyMethod()
is bound to the class instance object. In contrast, the first argument toMyClassMethod()
is bound to the class object itself (e.g., in this case,Test
). ForMyStaticMethod()
, none of the arguments are bound, and having arguments at all is optional."Static Variables"
However, implementing "static variables" (well, mutable static variables, anyway, if that's not a contradiction in terms...) is not as straight forward. As millerdev pointed out in his answer, the problem is that Python's class attributes are not truly "static variables". Consider:
This is because the line
x.i = 12
has added a new instance attributei
tox
instead of changing the value of theTest
classi
attribute.Partial expected static variable behavior, i.e., syncing of the attribute between multiple instances (but not with the class itself; see "gotcha" below), can be achieved by turning the class attribute into a property:
Now you can do:
The static variable will now remain in sync between all class instances.
(NOTE: That is, unless a class instance decides to define its own version of
_i
! But if someone decides to do THAT, they deserve what they get, don't they???)Note that technically speaking,
i
is still not a 'static variable' at all; it is aproperty
, which is a special type of descriptor. However, theproperty
behavior is now equivalent to a (mutable) static variable synced across all class instances.Immutable "Static Variables"
For immutable static variable behavior, simply omit the
property
setter:Now attempting to set the instance
i
attribute will return anAttributeError
:One Gotcha to be Aware of
Note that the above methods only work with instances of your class - they will not work when using the class itself. So for example:
The line
assert Test.i == x.i
produces an error, because thei
attribute ofTest
andx
are two different objects.Many people will find this surprising. However, it should not be. If we go back and inspect our
Test
class definition (the second version), we take note of this line:Clearly, the member
i
ofTest
must be aproperty
object, which is the type of object returned from theproperty
function.If you find the above confusing, you are most likely still thinking about it from the perspective of other languages (e.g. Java or c++). You should go study the
property
object, about the order in which Python attributes are returned, the descriptor protocol, and the method resolution order (MRO).I present a solution to the above 'gotcha' below; however I would suggest - strenuously - that you do not try to do something like the following until - at minimum - you thoroughly understand why
assert Test.i = x.i
causes an error.REAL, ACTUAL Static Variables -
Test.i == x.i
I present the (Python 3) solution below for informational purposes only. I am not endorsing it as a "good solution". I have my doubts as to whether emulating the static variable behavior of other languages in Python is ever actually necessary. However, regardless as to whether it is actually useful, the below should help further understanding of how Python works.
UPDATE: this attempt is really pretty awful; if you insist on doing something like this (hint: please don't; Python is a very elegant language and shoe-horning it into behaving like another language is just not necessary), use the code in Ethan Furman's answer instead.
Emulating static variable behavior of other languages using a metaclass
A metaclass is the class of a class. The default metaclass for all classes in Python (i.e., the "new style" classes post Python 2.3 I believe) is
type
. For example:However, you can define your own metaclass like this:
And apply it to your own class like this (Python 3 only):
Below is a metaclass I have created which attempts to emulate "static variable" behavior of other languages. It basically works by replacing the default getter, setter, and deleter with versions which check to see if the attribute being requested is a "static variable".
A catalog of the "static variables" is stored in the
StaticVarMeta.statics
attribute. All attribute requests are initially attempted to be resolved using a substitute resolution order. I have dubbed this the "static resolution order", or "SRO". This is done by looking for the requested attribute in the set of "static variables" for a given class (or its parent classes). If the attribute does not appear in the "SRO", the class will fall back on the default attribute get/set/delete behavior (i.e., "MRO").Static methods in python are called classmethods. Take a look at the following code
Notice that when we call the method myInstanceMethod, we get an error. This is because it requires that method be called on an instance of this class. The method myStaticMethod is set as a classmethod using the decorator @classmethod.
Just for kicks and giggles, we could call myInstanceMethod on the class by passing in an instance of the class, like so:
Personally I would use a classmethod whenever I needed a static method. Mainly because I get the class as an argument.
or use a decorator
For static properties.. Its time you look up some python definition.. variable can always change. There are two types of them mutable and immutable.. Also, there are class attributes and instance attributes.. Nothing really like static attributes in the sense of java & c++
Why use static method in pythonic sense, if it has no relation whatever to the class! If I were you, I'd either use classmethod or define the method independent from the class.
One very interesting point about Python's attribute lookup is that it can be used to create "virtual variables":
Normally there aren't any assignments to these after they are created. Note that the lookup uses
self
because, althoughlabel
is static in the sense of not being associated with a particular instance, the value still depends on the (class of the) instance.When define some member variable outside any member method, the variable can be either static or non-static depending on how the variable is expressed.
For example:
The results are