class Point(object):
pass
Point.ORIGIN = Point()
Answer from Ignacio Vazquez-Abrams on Stack OverflowCan a python class have a class variable of this same class? - Stack Overflow
Support different type for class variable and instance variable - Typing - Discussions on Python.org
Confused about class variables, also with inheritance
When to use class variables vs instance variables
Videos
Short answer is - yes, it's the right way. I would add a type hint for readability:
class ClassName:
Origin: 'ClassName'
There is actually a similar question Class variables of same type as the class. Some solutions are over-complicated, and I can't imagine use cases for them really.
Would a "metaclass" work any better for you? Perhaps something like:
class XY_Meta(type):
def __init__(cls, name, bases, dct):
cls.Origin = cls(0, 0)
class XY(metaclass=XY_Meta):
def __init__(self, x, y):
self.x = x
self.y = y
point = XY(10, 10)
print(point.x, point.y, point.Origin.x, point.Origin.y)
I think that might give you:
10 10 0 0
I'm finding class variables super confusing. I thought they were just like static variables in C++ (which instances can't own), but it seems they have quite different behavior.
Basic Class variable behavior - is this correct?
class Foo: x: int
-
if you set
Foo.x, it overrides the value of.xfor all instances of Foo, but -
if you set
.xon an instance ofFoo, it only changes.xon that instance.
edit: actually this can't be the full story, because sometimes changing Foo.x doesn't change the instance's .x??
Class variables + inheritance, what is going on?
class Parent: x: int class Child(Parent): pass Parent.x = 1 print(Child.x) # = 1. ok so child inherits parent class variable Child.x = 2 print(Parent.x) # = 1. ok, so child cannot set parent class variable Parent.x = 3 print(Child.x) # = 2. hol' up, now child doesn't inherit from parent anymore?
Also, if multiple classes inherit from Parent, if I set Child1.x does it affect the other children? How are instances affected too?
Class variables without declaration works too...?
What's the point of defining these variables in the class body if you don't need to?
class Foo: pass Foo.x = 3
I feel like there's some kind of mental model for class variables I'm just not understanding. Is there any easy way to think about them? Also is there any other weird behavior I should know?
I thought I understood the use cases for class vs instance variables:
-
Class: when you want the variable to be the same across all objects
-
Instance: when you want the variable to be unique to each object
But I'm working through the Codecademy DSA with Python course, and doing an implementation of a hash map. The hashing function (.hash()) finds the byte-code version of the key string, and sums it for the hash. Why is Codecademy's solution of key_bytes using a class variable, vs I thought an instance variable is more appropriate? Because for each hash map I make, I will want a unique key_byte per object?
class HashMap:
def __init__(self, array_size):
self.array_size = array_size
self.array = [None for item in range(array_size)]
def hash(self, key):
#codecademy forces this `key_bytes` as a class variable as solution
key_bytes = key.encode()
self.hash_code = sum(key_bytes)
#why is `key_bytes` not an instance variable:
self.key_bytes = key.encode()
self.hash_code = sum(self.key_bytes)You can use a property like the other answers put it - so, if you want to constrain a single attribute, say "bar", and constrain it to an integer, you could write code like this:
class Foo(object):
def _get_bar(self):
return self.__bar
def _set_bar(self, value):
if not isinstance(value, int):
raise TypeError("bar must be set to an integer")
self.__bar = value
bar = property(_get_bar, _set_bar)
And this works:
>>> f = Foo()
>>> f.bar = 3
>>> f.bar
3
>>> f.bar = "three"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in _set_bar
TypeError: bar must be set to an integer
>>>
(There is also a new way of writing properties, using the "property" built-in as a decorator to the getter method - but I prefer the old way, like I put it above).
Of course, if you have lots of attributes on your classes, and want to protect all of them in this way, it starts to get verbose. Nothing to worry about - Python's introspection abilities allow one to create a class decorator that could automate this with a minimum of lines.
def getter_setter_gen(name, type_):
def getter(self):
return getattr(self, "__" + name)
def setter(self, value):
if not isinstance(value, type_):
raise TypeError(f"{name} attribute must be set to an instance of {type_}")
setattr(self, "__" + name, value)
return property(getter, setter)
def auto_attr_check(cls):
new_dct = {}
for key, value in cls.__dict__.items():
if isinstance(value, type):
value = getter_setter_gen(key, value)
new_dct[key] = value
# Creates a new class, using the modified dictionary as the class dict:
return type(cls)(cls.__name__, cls.__bases__, new_dct)
And you just use auto_attr_checkas a class decorator, and declar the
attributes you want in the class body to be equal to the types the attributes need to constrain too:
...
... @auto_attr_check
... class Foo(object):
... bar = int
... baz = str
... bam = float
...
>>> f = Foo()
>>> f.bar = 5; f.baz = "hello"; f.bam = 5.0
>>> f.bar = "hello"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in setter
TypeError: bar attribute must be set to an instance of <type 'int'>
>>> f.baz = 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in setter
TypeError: baz attribute must be set to an instance of <type 'str'>
>>> f.bam = 3 + 2j
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in setter
TypeError: bam attribute must be set to an instance of <type 'float'>
>>>
Since Python 3.5, you can use type-hints to indicate that a class attribute should be of a particular type. Then, you could include something like MyPy as part of your continuous integration process to check that all the type contracts are respected.
For example, for the following Python script:
class Foo:
x: int
y: int
foo = Foo()
foo.x = "hello"
MyPy would give the following error:
6: error: Incompatible types in assignment (expression has type "str", variable has type "int")
If you want types to be enforced at runtime, you could use the enforce package. From the README:
>>> import enforce
>>>
>>> @enforce.runtime_validation
... def foo(text: str) -> None:
... print(text)
>>>
>>> foo('Hello World')
Hello World
>>>
>>> foo(5)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/william/.local/lib/python3.5/site-packages/enforce/decorators.py", line 106, in universal
_args, _kwargs = enforcer.validate_inputs(parameters)
File "/home/william/.local/lib/python3.5/site-packages/enforce/enforcers.py", line 69, in validate_inputs
raise RuntimeTypeError(exception_text)
enforce.exceptions.RuntimeTypeError:
The following runtime type errors were encountered:
Argument 'text' was not of type <class 'str'>. Actual type was <class 'int'>.
I am more familiar with C++ so maybe this isn't the python way to do things, but I want to overload the __init__ function of my class "Component" so that I can construct a new object of that type by passing an object of that type that already exists. Reason for doing it this way is that the class has a parent/child structure and so copying the parent requires careful handling of the family tree, I aim to solve this eventually with recursion, using this overloaded constructor as an aid to avoid bloating my copying function with loads of setter lines setting new objects to their appropriate values.
Currently my class that drives from Component (Group) looks like this:
from Components.component import Component, ComponentType
class Group(Component):
def __init__(self,
component_name: str,
):
if component_name is None:
component_name = "New Group"
super().__init__(component_name=component_name, component_type=ComponentType.Group)
self.children: list[Component] = []
def __init__(self, clone: Group): <- This line claims unresolved reference to group, but it is a member of that class!
pass
def add_child(self, new_child: Component):
if new_child not in self.children:
self.children.append(new_child)
else:
print(f"Oh no! {new_child.component_name} is already owned by {self.component_name}!")
def remove_child(self, old_child: Component):
if old_child in self.children:
self.children.remove(old_child)Feel free to tell me I'm handling this totally wrong! It's just the way that came to mind when looking to solve my current problem haha.
So I come from a Java background where defining, declaring and accessing static and instance level variables are pretty much a straightforward process. I want to be able to understand OOP concepts of Python properly so I have been doing some practice.
I have a class:
class A:
def init(self): pass
def someFunc(self): self.var1 += 1
I create an object of this class and call the someFunc() method:
a = A() a.someFunc()
It gives me an error. Ok, fair enough since I haven't declared a self.var1 variable yet.
Consider another example.
class A:
var1 = 10
def init(self): pass
def someFunc(self): self.var1 += 1
Now when I do this:
a = A() a.someFunc() Output: 11
I know that variables defined just below the class definition are class/static variables. And to access them you have to do A.var1
But why does it not give me an error now? I haven't created a object/instance level self.var1 variable yet, just a class level variable var1.
And when I call A.var1 the output is 10. Why is the output not the same as a.var1?
Does python automatically use the class level variable with the same name since there is no instance level variable defined with the same name? And does that in turn become a different variable from the class level variable?
Can someone please elaborate?