Python Static Class attributes [duplicate] - python

This question already has answers here:
Class (static) variables and methods
(27 answers)
Closed 8 years ago.
Is it possible in Python make a static attribute of class which will be same for all instances (objects) of that class, they all will use same reference to that attribute without creating their own attributes.
For example :
class myClass:
__a = 0
def __init__(self, b, c):
self.b = b
self.c = c
def increase_A(self):
self.__a += 1
return
def get_A(self):
return self.__a
So if I have
myObject1 = myClass(1,2)
myObject2 = myClass(3,4)
myObject2.increase_A()
print myObject1.get_A()
will show one and not zero, couse they share the same variable ?

To make your code work as it appears you intend, use myClass.__a to access the variable, instead of self.__a.
def increase_A(self):
myClass.__a += 1
return
def get_A(self):
return myClass.__a

They start off as the same variable. However, when you do
self.__a += 1
this rebinds the object's __a to a new object whose value is 1.
It does not change any other object's __a so the code will print out 0.

Related

Is it possible to call parent class-private methods from child class in Python? [duplicate]

This question already has answers here:
Getting parent private or protected values from the child class
(2 answers)
Closed 8 months ago.
I'm trying to call __search from parent class A in child class B but I get the error:
AttributeError: 'B' object has no attribute '_B__search'
This seems to be only happening for methods starting with __. Is there a way to call these class-private methods when doing inheritance?
class A:
def __init__(self, a):
self.a = a
def __search(self):
return self.a
def display(self):
print(self.a)
class B(A):
def display(self):
res = self.__search()
return res
cB = B(2)
cB.display()
Yes, but it's terrible practice.
In Python, a method whose name begins with __ and does not end with it (so magic methods like __add__ are excluded) is obfuscated with the class name. That is,
class A:
def __foo(self):
return 1
is equivalent to
class A:
def _A__foo(self):
return 1
So if you really want to call __search defined on A, you should write
res = self._A__search()
Again, this is bad practice. Methods starting with __ are obfuscated because that's the Python convention for private functions, so they shouldn't be called from outside the class or in subclasses. You mention in the comments that this is a temporary fix, so that's understandable, but I do hope it's not intended to stay this way for very long.
An attribute name beginning with __ is private, and mangled to _classname__attribute. You need to call it by the mangled name.
class B(A):
def display(self):
res = self._A__search()
return res

Avoid class instances to overwrite default values [duplicate]

This question already has answers here:
"Least Astonishment" and the Mutable Default Argument
(33 answers)
Python constructor and default value [duplicate]
(4 answers)
Closed 3 years ago.
I am dealing with issues regarding initialization of classes. Here is a reproducing example highlighting the underlying issue (I did not manage to make it much smaller):
Classes
We have two classes A,B. The hierarchy goes
A: First class - instances have two attributes link;name
B: This class has an A-instance as one of its attributes.
In order to faster declare instances of B I considered the following: B(name=name) which behind the curtains does B(a=A(name=name)).
Here is the code
class A(object):
def __init__(self, link='', name=''):
self.name = name
self.link = link
class B(object):
def __init__(self, a=A(), value=0, link='', name=''):
# Two ways to initialize "self.a":
# 1. If "name" or "link" provided
# 2. With "a" provided
if {name, link}.difference({''}):
self.a = A(name=name, link=link)
else:
self.a = a
# Rest
self.value = value
def __str__(self):
return 'Instance:\nname:\t{}\nlink:\t{}\nvalue:\t{}'.format(self.a.name, self.a.link, self.value)
Test
Here are two small tests:
The first one defines two instances b1;b2 using __init__.
The second one defines the instances as empty (B()) and then proceeds to populate/overwrite the fields.
As one can see below, the second option is problematic as it overwrites the classe's default values.
# 1. Set it all inside init
b1 = B(link=link, name=name, value=value)
b2 = B(value=value)
print(b1)
# Instance:
# name: world
# link: hello
# value: 1
print(b2)
# Instance:
# name:
# link:
# value: 1
# NO PROBLEM
# 2. Define empty instances and populate
b1 = B()
b1.a.link = link
b1.a.name = name
b1.value = values[0]
b2 = B()
b2.value = values[1]
print(b1)
# Instance:
# name: world
# link: hello
# value: 1
print(b2)
# Instance:
# name: world
# link: hello
# value: 2
# PROBLEM
How can I guarantee for this problem not to occurr? Should I overwrite the __new__ method, add getters/setter, work with copies (copy.deepcopy), etc. ?

what is the difference between a function and a callable object in python? [duplicate]

This question already has answers here:
Functions, Callable Objects, and how both are created in Python
(2 answers)
Closed 5 years ago.
class Adder:
def __call__(self, x, y):
return x + y
add1 = Adder()
def add2(x, y):
return x + y
What's the difference between add1 and add2 other than the type?
In your super-simple example. there's no practical difference, since functions are also callable objects.
However, a callable object is an object of a class that you write, so you may write this code:
class Counter:
def __init__(self, value = 0):
self.n = 0
def __call__(self):
self.n += 1
return self.n
def __repr__(self):
return str(self.n)
redWins = Counter()
blueWins = Counter()
if foo():
redWins()
else:
blueWins()
print("Red has won {} times.\nBlue has won {} times."
.format(redWins, blueWins))
And you'll find it hard to implement such a class using only functions. Even if you try to do it with global variables, you can't have separate instances of one single global variable.
See more: Functions, Callable Objects, and how both are created in Python
In your example, there's no functional difference but since add1 is an object, you can store information in the members:
class Adder:
def __init__(self):
self.__memory = 0
def __call__(self, x, y):
self.__memory += x
return x+y+self.__memory
add1 = Adder()
print(add1(10,10))
print(add1(10,10))
you get 30 then 40. You can do that with a function, but then you need a global variable, and using global variables is really asking for trouble.

How to print object from within a list [duplicate]

This question already has answers here:
Confused about __str__ on list in Python [duplicate]
(8 answers)
Closed 5 years ago.
I have a simple class I created:
class C:
def __init__(self):
self.a = 1
and I want to print a list of objects from this class using a function I created:
def p(s):
print('hi ', s)
This is how I want to call the printing function p: p([C() for i in range(3)])
Unfortunately, this produces hi [<__main__.C object at 0x000000F92A8B9080>, <__main__.C object at 0x000000F92AB0E898>, <__main__.C object at 0x000000F92AB0E978>].
I thought the problem was due to not implementing __str__ so I changed my class into:
class C:
def __init__(self):
self.a = 1
def __str__(self):
return str(self.a)
but I get the same result :(
What I hoped for was hi [1, 1, 1] or hi 1, 1, 1 or something like that, not the memory location of the objects I created.
I can use
for i in range(3):
p(C())
but I want to pass a list of objects to the p function rather than call it for each of my objects. Is that possible?
Replace __str__ with __repr__:
def __repr__(self):
return str(self.a)

Why are instances of this class being overwritten? [duplicate]

This question already has answers here:
Meaning of #classmethod and #staticmethod for beginner [duplicate]
(12 answers)
Closed 6 years ago.
I'm programming a script with Python using instances of FileHandler class but the second overwrites the first even without being assigned to the same variables.
The class:
class FileHandler():
name = None
path = None
#classmethod
def __init__(self,name,path):
self.name=name
self.path=path
#classmethod
def getName(self):
return self.name
#classmethod
def getPath(self):
return self.path
The script:
import fileHandler
origen=fileHandler.FileHandler('a','b')
destino=fileHandler.FileHandler('c','d')
print origen.getName(),origen.getPath()
print destino.getName(),destino.getPath()
The result:
c d
c d
You are using __init__ method as a class method.
Using #classmethod for every method will result in a singleton, that's why the vars overwrite.

Categories

Resources