Variables declared inside the class definition, but not inside a method are class or static variables:
>>> class MyClass:
... i = 3
...
>>> MyClass.i
3
As @millerdev points out, this creates a class-level i
variable, but this is distinct from any instance-level i
variable, so you could have
>>> m = MyClass()
>>> m.i = 4
>>> MyClass.i, m.i
>>> (3, 4)
This is different from C++ and Java, but not so different from C#, where a static member can't be accessed using a reference to an instance.
See what the Python tutorial has to say on the subject of classes and class objects.
@Steve Johnson has already answered regarding static methods, also documented under "Built-in Functions" in the Python Library Reference.
class C:
@staticmethod
def f(arg1, arg2, ...): ...
@beidy recommends classmethods over staticmethod, as the method then receives the class type as the first argument, but I'm still a little fuzzy on the advantages of this approach over staticmethod. If you are too, then it probably doesn't matter.
extend - adds the specified module's methods and constants to the target's metaclass (i.e. the singleton class)
e.g.
- if you call
Klazz.extend(Mod)
, now Klazz has Mod's methods (as class methods)
- if you call
obj.extend(Mod)
, now obj has Mod's methods (as instance methods), but no other instance of of obj.class
has those methods added.
extend
is a public method
include - By default, it mixes in the specified module's methods as instance methods in the target module/class.
e.g.
- if you call
class Klazz; include Mod; end;
, now all instances of Klazz have access to Mod's methods (as instance methods)
include
is a private method, because it's intended to be called from within the container class/module.
However, modules very often override include
's behavior by monkey-patching the included
method. This is very prominent in legacy Rails code. more details from Yehuda Katz.
Further details about include
, with its default behavior, assuming you've run the following code
class Klazz
include Mod
end
- If Mod is already included in Klazz, or one of its ancestors, the include statement has no effect
- It also includes Mod's constants in Klazz, as long as they don't clash
- It gives Klazz access to Mod's module variables, e.g.
@@foo
or @@bar
- raises ArgumentError if there are cyclic includes
- Attaches the module as the caller's immediate ancestor (i.e. It adds Mod to Klazz.ancestors, but Mod is not added to the chain of Klazz.superclass.superclass.superclass. So, calling
super
in Klazz#foo will check for Mod#foo before checking to Klazz's real superclass's foo method. See the RubySpec for details.).
Of course, the ruby core documentation is always the best place to go for these things. The RubySpec project was also a fantastic resource, because they documented the functionality precisely.
Best Solution
A class variable (
@@
) is shared among the class and all of its descendants. A class instance variable (@
) is not shared by the class's descendants.Class variable (
@@
)Let's have a class Foo with a class variable
@@i
, and accessors for reading and writing@@i
:And a derived class:
We see that Foo and Bar have the same value for
@@i
:And changing
@@i
in one changes it in both:Class instance variable (
@
)Let's make a simple class with a class instance variable
@i
and accessors for reading and writing@i
:And a derived class:
We see that although Bar inherits the accessors for
@i
, it does not inherit@i
itself:We can set Bar's
@i
without affecting Foo's@i
: