What better way to get around the "static variables" in Python? - python

It seems that in Python, to declare a variable in a class, it is static (keeps its value in the next instances). What better way to get around this problem?
class Foo():
number = 0
def set(self):
self.number = 1
>>> foo = Foo()
>>> foo.number
0
>>> foo.set()
>>> foo.number
1
>>> new_foo = Foo()
>>> new_foo.number
1

Variables defined at the class level are indeed "static", but I don't think they work quite the way you think they do. There are 2 levels here which you need to worry about. There are attributes at the class level, and there are attributes at the instance level. Whenever you do self.attribute = ... inside a method, you're setting an attribute at the instance level. Whenever python looks up an attribute, it first looks at the instance level, if it doesn't find the attribute, it looks at the class level.
This can be a little confusing (especially if the attribute is a reference to a mutable object). consider:
class Foo(object):
attr = [] #class level attribute is Mutable
def __init__(self):
# in the next line, self.attr references the class level attribute since
# there is no instance level attribute (yet)
self.attr.append('Hello')
self.attr = []
# Now, we've created an instance level attribute, so further appends will
# append to the instance level attribute, not the class level attribute.
self.attr.append('World')
a = Foo()
print (a.attr) #['World']
print (Foo.attr) #['Hello']
b = Foo()
print (b.attr) #['World']
print (Foo.attr) #['Hello', 'Hello']
As others have mentioned, if you want an attribute to be specific to an instance, just initialize it as an instance attribute in __init__ (using self.attr = ...). __init__ is a special method which is run whenever a class is initialized (with a few exceptions that we won't discuss here).
e.g.
class Foo(object):
def __init__(self):
self.attr = 0

Just leave the declaration out. If you want to provide default values for the variables, initialize them in the __init__ method instead.
class Foo(object):
def __init__(self):
self.number = 0
def set(self):
self.number = 1
>>> foo = Foo()
>>> foo.number
0
>>> foo.set()
>>> foo.number
1
>>> new_foo = Foo()
>>> new_foo.number
0
Edit: replaced last line of the above snippet; it used to read 1 although it was just a typo on my side. Seems like it has caused quite a bit of confusion while I was away.

You maybe want to change the class attribute:
class Foo():
number = 0
def set(self):
Foo.number = 1
instead of overriding it!

Related

Re-defining already assigned python class

I am new to Python and I inherited someone's code that had the following code structure. Why do I get an object not callable and how can I redefine this method again even after re-assigning l.bar. Another question would therefore be what's the difference between l.bar and l.bar()?
>>> class foo(object):
... def __init__(self):
... self.name = "Food"
... class bar(object):
... def __init__(self):
... self.name = "Is"
... class tea(object):
... def __init__(self):
... self.name = "Good"
...
>>> l = foo()
>>> m = l.bar()
>>> m.name = "Was"
>>> l.bar = m
>>> r = l.bar()
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: 'bar' object is not callable
As others have pointed out, it's generally not good practice to have nested classes. But, here's a breakdown of what's happening:
class foo(object):
def __init__(self):
self.name = "Food"
class bar(object):
def __init__(self):
self.name = "Is"
class tea(object):
def __init__(self):
self.name = "Good"
l = foo() # l is now an instance of foo
print l.name # "Food"
m = l.bar() # m is now an instance of bar
print m.name # "Is"
m.name = "Was" # you've assigned m's name to "Was"
print m.name # "Was"
l.bar = m # you are overriding foo's nested bar class now with an instance of bar
print l.name # "Food"
print l.bar # <__main__.bar object at 0x108371ad0>: this is now an instance, not a class
print l.bar.name # "Was"
r = l.bar() # you are now trying to call an instance of bar
The last line doesn't work because of the same reasons calling l() or foo()() doesn't work.
If you absolutely must figure out a way to make foo.bar().name return something else, you can create a new class and reassign foo.bar to it. But, this is really gross and not recommended. Hopefully, you can just change that original code.
print foo.bar().name # "Is"
class NewBar(object):
def __init__(self):
self.name = 'Was'
foo.bar = NewBar
print foo.bar().name # "Was"
Why do i get an object not callable
You assigned l.bar to be an instance of the class foo.bar (specifically, you assigned m to it). Instances of that class aren't callable, therefore l.bar isn't callable.
how can i redefine this method again even after re-assigning l.bar
Maybe this advice is too obvious, but don't re-assign l.bar.
However, you can reset l.bar so that it refers to the method it originally referred to, by doing del l.bar.
The reason this works is because if the individual object has no bar attribute of its own, then Python looks next to see whether its class has an attribute of the same name. So, to begin with the expression l.bar evaluates to the class foo.bar, since l has type foo. Then you assigned l a bar attribute of its own, so l.bar suddenly starts evaluating to that object instead. You can restore normality by deleting the object's own attribute.
what's the difference between l.bar and l.bar()
l.bar just gets the value of the attribute bar from the object l (or from its class, if the object l doesn't have one of its own, as explained above. If that fails too it'd go to base classes). l.bar() gets the value of that attribute and then calls it. () at this position means a function call, so the thing you put it after had better be callable.
It is not clear which of the following problems you are experiencing:
1. indentation issue
When copy-pasting from source to terminal, indentation sometimes gets messed up. in ipython you can use %paste to safely paste code.
The correctly indented class declarations are:
class foo(object):
def __init__(self):
self.name = "Food"
class bar(object):
def __init__(self):
self.name = "Is"
class tea(object):
def __init__(self):
self.name = "Good"
But then the other commands make no sense.
2. instance is not the same as class
When defining a class inside a class, you have to use the outer class name to "get" to the inner class name. I.e.:
class foo(object):
def __init__(self):
self.name = "Food"
class bar(object):
def __init__(self):
self.name = "Is"
class tea(object):
def __init__(self):
self.name = "Good"
foo_inst = foo()
bar_inst = foo.bar()
tea_inst = foo.bar.tea()
Anyhow, these lines still make not much sense:
>>> l.bar = m
>>> r = l.bar()
Why would you want to override bar which is (was) a class name...

Turning an attribute into a property on an object-by-object basis?

I have a class of objects, most of whom have this one attribute which can in 95% of cases be implemented as a simple attribute. However, there are a few important edge cases where that property must be computed from data on another object.
What I'd like to be able to do is set myobj.gnarlyattribute = property(lambda self: self.container.x*self.k).
However, this doesn't seem to work:
>>> myfoo=foo()
>>> myfoo.spam
10
>>> import random
>>> myfoo.spam=property(lambda self: random.randint(0,20))
>>> myfoo.spam
<property object at 0x02A57420>
>>>
I suppose I could have gnarlyattribute always be a property which usually just has lambda self: self._gnarlyattribute as the getter, but that seems a little smelly. Any ideas?
As has already been pointed out, properties can only work at the class level, and they can't be set on instances. (Well, they can, but they don't do what you want.)
Therefore, I suggest using class inheritance to solve your problem:
class NoProps(object):
def __init__(self, spam=None):
if spam is None:
spam = 0 # Pick a sensible default
self.spam = spam
class Props(NoProps):
#property
def spam(self):
"""Docstring for the spam property"""
return self._spam
#spam.setter
def spam(self, value):
# Do whatever calculations are needed here
import random
self._spam = value + random.randint(0,20)
#spam.deleter
def spam(self):
del self._spam
Then when you discover that a particular object needs to have its spam attribute as a calculated property, make that object an instance of Props instead of NoProps:
a = NoProps(3)
b = NoProps(4)
c = Props(5)
print a.spam, b.spam, c.spam
# Prints 3, 4, (something between 5 and 25)
If you can tell ahead of time when you'll need calculated values in a given instance, that should do what you're looking for.
Alternately, if you can't tell that you'll need calculated values until after you've created the instance, that one's pretty straightforward as well: just add a factory method to your class, which will copy the properties from the "old" object to the "new" one. Example:
class NoProps(object):
def __init__(self, spam=None):
if spam is None:
spam = 0 # Pick a sensible default
self.spam = spam
#classmethod
def from_other_obj(cls, other_obj):
"""Factory method to copy other_obj's values"""
# The call to cls() is where the "magic" happens
obj = cls()
obj.spam = other_obj.spam
# Copy any other properties here
return obj
class Props(NoProps):
#property
def spam(self):
"""Docstring for the spam property"""
return self._spam
#spam.setter
def spam(self, value):
# Do whatever calculations are needed here
import random
self._spam = value + random.randint(0,20)
#spam.deleter
def spam(self):
del self._spam
Since we call cls() inside the factory method, it will make an instance of whichever class it was invoked on. Thus the following is possible:
a = NoProps(3)
b = NoProps.from_other_obj(a)
c = NoProps.from_other_obj(b)
print(a.spam, b.spam, c.spam)
# Prints 3, 3, 3
# I just discovered that c.spam should be calculated
# So convert it into a Props object
c = Props.from_other_obj(c)
print(a.spam, b.spam, c.spam)
# Prints 3, 3, (something between 3 and 23)
One or the other of these two solutions should be what you're looking for.
The magic to make properties work only exists at the class level. There is no way to make properties work per-object.

Python: How to do extra stuff when a specific attribute of an object is accessed?

Let's say I have a class in Python:
class Foo(object):
a = 1
b = 2
I'd like to do some extra stuff when I access 'a' but NOT 'b'. So, for example, let's assume that the extra stuff I'd like to do is to increment the value of the attribute:
> f = Foo()
> f.a # Should output 2
> f.a # Should output 3
> f.a # Should output 4
> f.b # Should output 2, since I want the extra behavior just on 'a'
It feels like there is a way through __getattr__ or __getattribute__, but I couldn't figure that out.
The extra thing can be anything, not necessarily related to the attribute (like print 'Hello world').
Thanks.
What you are looking for is a property, which can be used nicely as a decorator:
class Foo(object):
_a = 2
#property
def a(self):
Foo._a += 1
return Foo._a - 1
b = 2
The function is called whenever you try to access foo_instance.a, and the value returned is used as the value for the attribute. You can also define a setter too, which is called with the new value when the attribute is set.
This is presuming you want the odd set-up of class attributes you only ever access from instances. (_a and b here belong to the class - that is, there is only one variable shared by all instances - as in your question). A property, however, is always instance-owned. The most likely case is you actually want:
class Foo(object):
def __init__(self):
self._a = 2
self.b = 2
#property
def a(self):
self._a += 1
return self._a - 1
Where they are instance attributes.
If you really do want the equivalent of #property for a class variable, you have to build the descriptor yourself.
You almost certainly don't want to do this—see Lattyware's answer for how to make normal instance variables, and turn one of them into a #property.
But here's how you could do it:
class IncrementOnGetDescriptor(object):
def __init__(self, initval=None):
self.val = initval
def __get__(self, obj, objtype):
self.val += 1
return self.val - 1
def __set__(self, obj, val):
self.val = val
class Foo(object):
a = IncrementOnGetDescriptor(2)
b = 2
Now you can test it:
>>> f = Foo()
>>> f.a
2
>>> Foo.a
3
>>>> f.a
4
Turning this into a #classproperty decorator is left as an exercise for the reader.
PS, this still isn't exactly like a normal class variable. Setting Foo.a = 10 will replace your magic auto-incrementing value with a normal 10, while setting foo.a = 10 will update the class with an auto-incrementing 10 instead of storing an instance variable in f. (I originally had the __set__ method raise AttributeError, because normally you'd want an auto-incrementing magic variable be read-only, but I decided to show the more complex version just to show all the issues you have to deal with.)

How to keep track of class instances?

Toward the end of a program I'm looking to load a specific variable from all the instances of a class into a dictionary.
For example:
class Foo():
def __init__(self):
self.x = {}
foo1 = Foo()
foo2 = Foo()
...
Let's say the number of instances will vary and I want the x dict from each instance of Foo() loaded into a new dict. How would I do that?
The examples I've seen in SO assume one already has the list of instances.
One way to keep track of instances is with a class variable:
class A(object):
instances = []
def __init__(self, foo):
self.foo = foo
A.instances.append(self)
At the end of the program, you can create your dict like this:
foo_vars = {id(instance): instance.foo for instance in A.instances}
There is only one list:
>>> a = A(1)
>>> b = A(2)
>>> A.instances
[<__main__.A object at 0x1004d44d0>, <__main__.A object at 0x1004d4510>]
>>> id(A.instances)
4299683456
>>> id(a.instances)
4299683456
>>> id(b.instances)
4299683456
#JoelCornett's answer covers the basics perfectly. This is a slightly more complicated version, which might help with a few subtle issues.
If you want to be able to access all the "live" instances of a given class, subclass the following (or include equivalent code in your own base class):
from weakref import WeakSet
class base(object):
def __new__(cls, *args, **kwargs):
instance = object.__new__(cls, *args, **kwargs)
if "instances" not in cls.__dict__:
cls.instances = WeakSet()
cls.instances.add(instance)
return instance
This addresses two possible issues with the simpler implementation that #JoelCornett presented:
Each subclass of base will keep track of its own instances separately. You won't get subclass instances in a parent class's instance list, and one subclass will never stumble over instances of a sibling subclass. This might be undesirable, depending on your use case, but it's probably easier to merge the sets back together than it is to split them apart.
The instances set uses weak references to the class's instances, so if you del or reassign all the other references to an instance elsewhere in your code, the bookkeeping code will not prevent it from being garbage collected. Again, this might not be desirable for some use cases, but it is easy enough to use regular sets (or lists) instead of a weakset if you really want every instance to last forever.
Some handy-dandy test output (with the instances sets always being passed to list only because they don't print out nicely):
>>> b = base()
>>> list(base.instances)
[<__main__.base object at 0x00000000026067F0>]
>>> class foo(base):
... pass
...
>>> f = foo()
>>> list(foo.instances)
[<__main__.foo object at 0x0000000002606898>]
>>> list(base.instances)
[<__main__.base object at 0x00000000026067F0>]
>>> del f
>>> list(foo.instances)
[]
You would probably want to use weak references to your instances. Otherwise the class could likely end up keeping track of instances that were meant to have been deleted. A weakref.WeakSet will automatically remove any dead instances from its set.
One way to keep track of instances is with a class variable:
import weakref
class A(object):
instances = weakref.WeakSet()
def __init__(self, foo):
self.foo = foo
A.instances.add(self)
#classmethod
def get_instances(cls):
return list(A.instances) #Returns list of all current instances
At the end of the program, you can create your dict like this:
foo_vars = {id(instance): instance.foo for instance in A.instances}
There is only one list:
>>> a = A(1)
>>> b = A(2)
>>> A.get_instances()
[<inst.A object at 0x100587290>, <inst.A object at 0x100587250>]
>>> id(A.instances)
4299861712
>>> id(a.instances)
4299861712
>>> id(b.instances)
4299861712
>>> a = A(3) #original a will be dereferenced and replaced with new instance
>>> A.get_instances()
[<inst.A object at 0x100587290>, <inst.A object at 0x1005872d0>]
You can also solve this problem using a metaclass:
When a class is created (__init__ method of metaclass), add a new instance registry
When a new instance of this class is created (__call__ method of metaclass), add it to the instance registry.
The advantage of this approach is that each class has a registry - even if no instance exists. In contrast, when overriding __new__ (as in Blckknght's answer), the registry is added when the first instance is created.
class MetaInstanceRegistry(type):
"""Metaclass providing an instance registry"""
def __init__(cls, name, bases, attrs):
# Create class
super(MetaInstanceRegistry, cls).__init__(name, bases, attrs)
# Initialize fresh instance storage
cls._instances = weakref.WeakSet()
def __call__(cls, *args, **kwargs):
# Create instance (calls __init__ and __new__ methods)
inst = super(MetaInstanceRegistry, cls).__call__(*args, **kwargs)
# Store weak reference to instance. WeakSet will automatically remove
# references to objects that have been garbage collected
cls._instances.add(inst)
return inst
def _get_instances(cls, recursive=False):
"""Get all instances of this class in the registry. If recursive=True
search subclasses recursively"""
instances = list(cls._instances)
if recursive:
for Child in cls.__subclasses__():
instances += Child._get_instances(recursive=recursive)
# Remove duplicates from multiple inheritance.
return list(set(instances))
Usage: Create a registry and subclass it.
class Registry(object):
__metaclass__ = MetaInstanceRegistry
class Base(Registry):
def __init__(self, x):
self.x = x
class A(Base):
pass
class B(Base):
pass
class C(B):
pass
a = A(x=1)
a2 = A(2)
b = B(x=3)
c = C(4)
for cls in [Base, A, B, C]:
print cls.__name__
print cls._get_instances()
print cls._get_instances(recursive=True)
print
del c
print C._get_instances()
If using abstract base classes from the abc module, just subclass abc.ABCMeta to avoid metaclass conflicts:
from abc import ABCMeta, abstractmethod
class ABCMetaInstanceRegistry(MetaInstanceRegistry, ABCMeta):
pass
class ABCRegistry(object):
__metaclass__ = ABCMetaInstanceRegistry
class ABCBase(ABCRegistry):
__metaclass__ = ABCMeta
#abstractmethod
def f(self):
pass
class E(ABCBase):
def __init__(self, x):
self.x = x
def f(self):
return self.x
e = E(x=5)
print E._get_instances()
Another option for quick low-level hacks and debugging is to filter the list of objects returned by gc.get_objects() and generate the dictionary on the fly that way. In CPython that function will return you a (generally huge) list of everything the garbage collector knows about, so it will definitely contain all of the instances of any particular user-defined class.
Note that this is digging a bit into the internals of the interpreter, so it may or may not work (or work well) with the likes of Jython, PyPy, IronPython, etc. I haven't checked. It's also likely to be really slow regardless. Use with caution/YMMV/etc.
However, I imagine that some people running into this question might eventually want to do this sort of thing as a one-off to figure out what's going on with the runtime state of some slice of code that's behaving strangely. This method has the benefit of not affecting the instances or their construction at all, which might be useful if the code in question is coming out of a third-party library or something.
Here's a similar approach to Blckknght's, which works with subclasses as well. Thought this might be of interest, if someone ends up here. One difference, if B is a subclass of A, and b is an instance of B, b will appear in both A.instances and B.instances. As stated by Blckknght, this depends on the use case.
from weakref import WeakSet
class RegisterInstancesMixin:
instances = WeakSet()
def __new__(cls, *args, **kargs):
o = object.__new__(cls, *args, **kargs)
cls._register_instance(o)
return o
#classmethod
def print_instances(cls):
for instance in cls.instances:
print(instance)
#classmethod
def _register_instance(cls, instance):
cls.instances.add(instance)
for b in cls.__bases__:
if issubclass(b, RegisterInstancesMixin):
b._register_instance(instance)
def __init_subclass__(cls):
cls.instances = WeakSet()
class Animal(RegisterInstancesMixin):
pass
class Mammal(Animal):
pass
class Human(Mammal):
pass
class Dog(Mammal):
pass
alice = Human()
bob = Human()
cannelle = Dog()
Animal.print_instances()
Mammal.print_instances()
Human.print_instances()
Animal.print_instances() will print three objects, whereas Human.print_instances() will print two.
Using the answer from #Joel Cornett I've come up with the following, which seems to work. i.e. i'm able to total up object variables.
import os
os.system("clear")
class Foo():
instances = []
def __init__(self):
Foo.instances.append(self)
self.x = 5
class Bar():
def __init__(self):
pass
def testy(self):
self.foo1 = Foo()
self.foo2 = Foo()
self.foo3 = Foo()
foo = Foo()
print Foo.instances
bar = Bar()
bar.testy()
print Foo.instances
x_tot = 0
for inst in Foo.instances:
x_tot += inst.x
print x_tot
output:
[<__main__.Foo instance at 0x108e334d0>]
[<__main__.Foo instance at 0x108e334d0>, <__main__.Foo instance at 0x108e33560>, <__main__.Foo instance at 0x108e335a8>, <__main__.Foo instance at 0x108e335f0>]
5
10
15
20
(For Python)
I have found a way to record the class instances via the "dataclass" decorator while defining a class. Define a class attribute 'instances' (or any other name) as a list of the instances you want to record. Append that list with the 'dict' form of created objects via the dunder method __dict__. Thus, the class attribute 'instances' will record instances in the dict form, which you want.
For example,
from dataclasses import dataclass
#dataclass
class player:
instances=[]
def __init__(self,name,rank):
self.name=name
self.rank=rank
self.instances.append(self.__dict__)

Is it safe to replace a self object by another object of the same type in a method?

I would like to replace an object instance by another instance inside a method like this:
class A:
def method1(self):
self = func(self)
The object is retrieved from a database.
It is unlikely that replacing the 'self' variable will accomplish whatever you're trying to do, that couldn't just be accomplished by storing the result of func(self) in a different variable. 'self' is effectively a local variable only defined for the duration of the method call, used to pass in the instance of the class which is being operated upon. Replacing self will not actually replace references to the original instance of the class held by other objects, nor will it create a lasting reference to the new instance which was assigned to it.
As far as I understand, If you are trying to replace the current object with another object of same type (assuming func won't change the object type) from an member function. I think this will achieve that:
class A:
def method1(self):
newObj = func(self)
self.__dict__.update(newObj.__dict__)
It is not a direct answer to the question, but in the posts below there's a solution for what amirouche tried to do:
Python object conversion
Can I dynamically convert an instance of one class to another?
And here's working code sample (Python 3.2.5).
class Men:
def __init__(self, name):
self.name = name
def who_are_you(self):
print("I'm a men! My name is " + self.name)
def cast_to(self, sex, name):
self.__class__ = sex
self.name = name
def method_unique_to_men(self):
print('I made The Matrix')
class Women:
def __init__(self, name):
self.name = name
def who_are_you(self):
print("I'm a women! My name is " + self.name)
def cast_to(self, sex, name):
self.__class__ = sex
self.name = name
def method_unique_to_women(self):
print('I made Cloud Atlas')
men = Men('Larry')
men.who_are_you()
#>>> I'm a men! My name is Larry
men.method_unique_to_men()
#>>> I made The Matrix
men.cast_to(Women, 'Lana')
men.who_are_you()
#>>> I'm a women! My name is Lana
men.method_unique_to_women()
#>>> I made Cloud Atlas
Note the self.__class__ and not self.__class__.__name__. I.e. this technique not only replaces class name, but actually converts an instance of a class (at least both of them have same id()). Also, 1) I don't know whether it is "safe to replace a self object by another object of the same type in [an object own] method"; 2) it works with different types of objects, not only with ones that are of the same type; 3) it works not exactly like amirouche wanted: you can't init class like Class(args), only Class() (I'm not a pro and can't answer why it's like this).
Yes, all that will happen is that you won't be able to reference the current instance of your class A (unless you set another variable to self before you change it.) I wouldn't recommend it though, it makes for less readable code.
Note that you're only changing a variable, just like any other. Doing self = 123 is the same as doing abc = 123. self is only a reference to the current instance within the method. You can't change your instance by setting self.
What func(self) should do is to change the variables of your instance:
def func(obj):
obj.var_a = 123
obj.var_b = 'abc'
Then do this:
class A:
def method1(self):
func(self) # No need to assign self here
In many cases, a good way to achieve what you want is to call __init__ again. For example:
class MyList(list):
def trim(self,n):
self.__init__(self[:-n])
x = MyList([1,2,3,4])
x.trim(2)
assert type(x) == MyList
assert x == [1,2]
Note that this comes with a few assumptions such as the all that you want to change about the object being set in __init__. Also beware that this could cause problems with inheriting classes that redefine __init__ in an incompatible manner.
Yes, there is nothing wrong with this. Haters gonna hate. (Looking at you Pycharm with your in most cases imaginable, there's no point in such reassignment and it indicates an error).
A situation where you could do this is:
some_method(self, ...):
...
if(some_condition):
self = self.some_other_method()
...
return ...
Sure, you could start the method body by reassigning self to some other variable, but if you wouldn't normally do that with other parametres, why do it with self?
One can use the self assignment in a method, to change the class of instance to a derived class.
Of course one could assign it to a new object, but then the use of the new object ripples through the rest of code in the method. Reassiging it to self, leaves the rest of the method untouched.
class aclass:
def methodA(self):
...
if condition:
self = replace_by_derived(self)
# self is now referencing to an instance of a derived class
# with probably the same values for its data attributes
# all code here remains untouched
...
self.methodB() # calls the methodB of derivedclass is condition is True
...
def methodB(self):
# methodB of class aclass
...
class derivedclass(aclass):
def methodB(self):
#methodB of class derivedclass
...
But apart from such a special use case, I don't see any advantages to replace self.
You can make the instance a singleton element of the class
and mark the methods with #classmethod.
from enum import IntEnum
from collections import namedtuple
class kind(IntEnum):
circle = 1
square = 2
def attr(y): return [getattr(y, x) for x in 'k l b u r'.split()]
class Shape(namedtuple('Shape', 'k,l,b,u,r')):
self = None
#classmethod
def __repr__(cls):
return "<Shape({},{},{},{},{}) object at {}>".format(
*(attr(cls.self)+[id(cls.self)]))
#classmethod
def transform(cls, func):
cls.self = cls.self._replace(**func(cls.self))
Shape.self = Shape(k=1, l=2, b=3, u=4, r=5)
s = Shape.self
def nextkind(self):
return {'k': self.k+1}
print(repr(s)) # <Shape(1,2,3,4,5) object at 139766656561792>
s.transform(nextkind)
print(repr(s)) # <Shape(2,2,3,4,5) object at 139766656561888>

Categories

Resources