Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am practicing python classes. I got that classes variables are shared among all the instances, while instance variables belongs to each object, and thus need to be defined for each instance. In the following classes, in reference to the variable raise_amount, if I write the last code line like that: self.pay = int(self.pay * Employee.raise_amount), the behavior is the same.
What is the difference between the two cases, if any?
class Employee:
raise_amount = 1.04
def __init__(self ,first ,last ,pay ):
self.first = first
self.last = last
self.pay = pay
self.email = first+"."+last+"#company.com"
def apply_raise(self): #but this is not an attribute
self.pay = int(self.pay * self.raise_amount)
#or self.pay = int(self.pay * Employee.raise_amount)
I assume your are referring to the self.raise_amount. In the case where you have it as that python must first look for instance variable and if not found it looks for similarly named class variable and creates a copy of it as an instance variable and uses that. if you were to then change the self.raise amount it would only be for the instance and not for any other instance made from the class.
Try creating an instance of the class and use the apply_raise method on it. then try changing the raise_amount class variable to something like 2.0 and call the method on the instance again. what you should see is that the amount only goes up 1.04 times, not 2. that is because it used the instance value it created the first time you ran the method.
Note: original post was edited to change to use the Class name for the raise amount. This post was a reply while it was self.raise_amount.
The lookup for the expression self.raise_amount can be complicated in general, be we can simplify it knowing that there are no methods or descriptors involved.
If self has an instance attribute named raise_amount, the value of that attribute is returned.
Otherwise, we start looking for class attributes, starting with the immediate type of self, here Employee. Since Employee.raise_amount is defined, we get that value...
... but what if Employee.raise_amount hadn't been defined? We would have moved on to the next class in the method resolution order of Employee, namely object. Since object.raise_amount is not defined, an AttributeError would have been raised.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 21 days ago.
Improve this question
I am trying to use one variable obtained from one function in other function. However , it gives error. Let me explain it wih my code.
class Uygulama(object):
def __init__(self):
self.araclar()
self.refresh()
self.gateway_find()
def refresh(self):
self.a, self.b = srp(Ether(dst="FF:FF:FF:FF:FF:FF") / ARP(pdst=self.ip_range2), timeout=2, iface="eth0",
retry=3)
#There are unrelated codes here
def gateway_find(self):
#Find ip any range in which you conncet:
self.ip_range=conf.route.route("0.0.0.0")[1]
self.ip_range1=self.ip_range.rpartition(".")[0]
self.ip_range2=self.iprange_1+".0/24"
When , run the foregoing codes , i get this error AttributeError: 'Uygulama' object has no attribute 'ip_range2'
How can i use such variable which are obtained from other function in the other function. How can i fix my problem ?
Call order of init functions
Place function that define attribute first
In the __init__ function, you call refresh, who use (need) ip_range2 before gateway_find who create the attribute and set a value to it. Swap the two lines, you should be fine.
def __init__(self):
self.araclar()
self.gateway_find() # gateway_find will set the ip_range attribute
self.refresh() # So refresh function will be able to access it
Usually, we place init functions first, then function that will call post-init processes like refresh.
Class attribute default value
Alternatively, you can define a default value for ip_range2 like this:
class Uygulama(object):
ip_range2 = None
def __init__(self):
self.araclar()
self.refresh()
self.gateway_find()
def refresh(self):
self.a, self.b = srp(Ether(dst="FF:FF:FF:FF:FF:FF") / ARP(pdst=self.ip_range2), timeout=2, iface="eth0", retry=3)
Be aware that such default value is shared with all other instances of the class if not redefined in __init__, so if it's a mutable (like a list), it might create really weird bugs.
Usually, prefer defining value in the __init__ like you do with the gateway fct.
That error explains correctly that you do not have a class attribute called ip_range2. You need to define the class attribute first.
class Uygulama(object):
ip_range2 = ''
...
then use that with self.ip_range2.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 months ago.
Improve this question
I've been going through Python tutorial for Python properties and I can't make any sense of this code:
# using property class
class Celsius:
def __init__(self, temperature=0):
self.temperature = temperature
def to_fahrenheit(self):
return (self.temperature * 1.8) + 32
# getter
def get_temperature(self):
print("Getting value...")
return self._temperature
# setter
def set_temperature(self, value):
print("Setting value...")
if value < -273.15:
raise ValueError("Temperature below -273.15 is not possible")
self._temperature = value
# creating a property object
temperature = property(get_temperature, set_temperature)
human = Celsius(37)
print(human.temperature)
print(human.to_fahrenheit())
human.temperature = -300
Why is the property being assigned outside of init?
where is self._temperature even defined?
How is self._temperature is linked to self.temperature even though these two are not linked together any where in the code?
How is it that in the to_fahrenheit function, even though that I'm changing self.temperature, it is self._temperature that gets changed not the original temperature that is defined in the constructor?
I'd really appreciate any help since this does not make any sense but works!
Your snippet illustrates the concept of getter and setter methods in Python. When attempting to set the temperature class variable (e.g. human.temperature = -300), Python does not actually modify human.temperature, but calls human.set_temperature(-300) instead, which, given no error is raised, sets human._temperature to the specified value. Similarly, calling print(human.temperature) is equivalent to print(human.get_temperature()) (try these replacements in your code and see what happens).
Moreover, the _ prefix of _temperature signal that it is a private variable, i.e. should not be used outside the class definition and the get_ / set_ prefix declares that the function is a getter / setter.
In conclusion, human.temperature does not hold a value, but rather calls human.get_temperature() or human.set_temperature() depending on the context. The actual value is stored in human._temperature. For a more detailed explanation, I suggest reading the aforementioned articles.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am currently learning Python at home using the Python for Dummies all in one book. I'm on the chapter about classes and in particular the section on class variables. So far, the code has been running fine, but I'm not sure why it doesn't work the way I expect.
My code is this:
class Crew_Member:
"""A class for creating an individual record"""
is_human = True
def __init__(self, full_name, username, rank="crewmember"):
self.full_name = full_name
self.username = username
self.rank = rank
self.join_date = dt.date.today()
def file_age(self):
return f"{self.full_name}'s file was created on {self.join_date:%d/%m/%y}"
def promote(self, rank):
self.rank = rank
def not_human(self):
if Crew_Member.is_human:
self.rank = "Mech/Scutter"
So my understanding is that is_human is the class variable. The method I'm trying to use it in is not_human. The idea is that each object would be the personel record for a crew member. If that crew member is not human, they automatically get the rank of "Mech/Scutter".
The way I imagined it working is after the object has been called, you change that instance's value of is_human to false, run the method not_human, and that would change their rank accordingly. The first time I tried and got the correct rank, the class variable hadn't changed:
My code (as written above) works fine, but this is what I have to enter to get it to work:
So this is my problem: The for (edit: if) loop in the not_human method says "If class variable is true, then change rank". But the class variable has been changed to false (as illustrated by the first print line) so why does it work?
But the class variable has been changed to false...
No, the line BobScutt.is_human = False turns it into an instance variable. The class variable remains untouched. If you want to change it, you have to manipulate the Crew_Member class directly, not one of its instances.
Observe:
class TestClass:
test_attr = True
foo = TestClass()
foo.test_attr = False
print("Test attribute in foo:", foo.test_attr)
print("Test attribute in TestClass:", TestClass.test_attr)
Output:
Test attribute in foo: False
Test attribute in TestClass: True
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I was looking for a way how we can modify existing staticmethod decorator in python to add custom behavior. Say, calling another method in a class each time a static method is used.
I was stuck in a problem with MongoDB which required calling a method to manually set the Collection Name.
The following points give a description of the problem I'm stuck at:
I made a Database Class which acted as a wrapper for pymongo
I made 2 classes which used the Database Class I made for making transaction with MongoDB
Collection name's assigned to each class as a static variable
Example :
User Class's collection name -> Users,
Quiz Class's collection name -> Quiz
Database Class (wrapper) maintained it's own static variable for Collection name, which was assigned by whichever class required to make transactions with the help of it.
The PROBLEM: Whenever I made a transaction for Quiz class first, it assigned Collection name to Database Class, but as soon as I made a transaction with User Class, Quiz Class's Collection name was used.
I made transactions using static methods in those Classes, The SOLUTION I thought of was modifying staticmethod in a way that it automatically reassigns the Collection name to the Database Class each time the static method is called.
Create a new decorator instead that calls staticmethod. I think this will work.
def customstatic(fun):
def decorator(*args, **kwargs):
def wrapper():
return fun(*args, **kwargs)
# do custom stuff here
return staticmethod(wrapper)
return decorator
To add an alternative to #blueteeth 's answer.
This works but most linters will complain about it.
def custom_method(func):
#staticmethod
def static(*args, **kwargs):
# do stuff
func(*args, **kwargs)
return static
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I want to call a variable created in a function (func) that is also in a class (A). Below is a very basic version of what I want to accomplish in my larger code. I am fairly new to coding so any help would be appreciated.
class A:
def func(self):
self.number = 1
print(A.number)
You need to read about static var : (copy/paste)
ref: https://www.geeksforgeeks.org/g-fact-34-class-or-static-variables-in-python/
You can run the code there to understand more
Class or Static Variables in Python
Class or static variables are shared by all objects. Instance or non-static variables are different for different objects (every object has a copy of it).
For example, let a Computer Science Student be represented by class CSStudent. The class may have a static variable whose value is “cse” for all objects. And class may also have non-static members like name and roll.
In C++ and Java, we can use static keyword to make a variable as class variable. The variables which don’t have preceding static keyword are instance variables. See this for Java example and this for C++ example.
The Python approach is simple, it doesn’t require a static keyword. All variables which are assigned a value in class declaration are class variables. And variables which are assigned values inside class methods are instance variables.
# Python program to show that the variables with a value
# assigned in class declaration, are class variables
# Class for Computer Science Student
class CSStudent:
stream = 'cse' # Class Variable
def __init__(self,name,roll):
self.name = name # Instance Variable
self.roll = roll # Instance Variable
# Objects of CSStudent class
a = CSStudent('Geek', 1)
b = CSStudent('Nerd', 2)
print(a.stream) # prints "cse"
print(b.stream) # prints "cse"
print(a.name) # prints "Geek"
print(b.name) # prints "Nerd"
print(a.roll) # prints "1"
print(b.roll) # prints "2"
# Class variables can be accessed using class
# name also
print(CSStudent.stream) # prints "cse"
CSStudent.stream = "foo"
print(a.stream) # prints "foo" (this variable litterally is CSStudent.stream)