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
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 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 1 year ago.
Improve this question
I have a following code:
import datetime
class Notebook:
def __init__(self):
self._id = 0
self.notes = []
def new_note(self, memo, tags=""):
self.notes.append(Note(self, memo, tags)) # creating Note object instance, passing Notebook object
def get_id(self):
id = self._id
self._id += 1
return id
class Note:
def __init__(self, notebook, memo="", tags=""):
self.id = notebook.get_id() # accesing Notebook object's get_id method to set a new unique id for a Note object
self.creation_date = datetime.date.today()
self.tags = tags
self.memo = memo
def __repr__(self):
return f"[{self.id}, {self.creation_date}, {self.tags}, {self.memo}]"
n = Notebook()
n.new_note("Lorem ipsum", "Latin")
print(n.notes)
This is an exercise code I created following a book on OOP. As you can see, I had to (as far as I can tell) pass the Notebook object to a Note object during the creation just to be able to get_id for my new Note object from the Notebook object which created it.
Is there a better way to do it? Is there another way to access the attribute from the creator class without passing the whole object? Is passing an object this way necessary a bad thing at all?
The main question is how to use get_id method of Notebook object from the Note object contained within self.notes attribute of the Notebook object, but without passing the whole Notebook object, as shown in the example.
Thanks!
This is not possible, and for good reason. Imagine that your class accepted that the user specifies the type of note when creating to allow for modification, or runs some user-specified code from the note. I could create a MyNote class that replaces the new_note method to record all of the new notes the user makes. That would be problematic.
Obviously this is not an issue because you have this hardcoded, but in a more secure and dynamic environment that lets the user specify, a well-disguised malicious class could access the secure class creating it. Such as if your bank decided to use a module that creates loading bars, where it should not be able to look into the class that instantiated it.
Granted, in a truly secure situation, all the code would be under your control anyways.
Another approach could be inheritance.this is assuming th id would auto-increment based on each notebook added to the notebook class. With inheritance you get to do away with some repetition of logic.
import datetime
class Note:
tags = None
memo = None
def __init__(self):
self.creation_date = datetime.date.today()
self.id = 0
def __repr__(self):
return 'Note created!'
class Notebook(Note):
def new_note(self,memo, tags=""):
self.tags = memo
self.memo = tags
return f"[{self.tok()}, {self.creation_date}, {self.tags}, {self.memo}]"
def gen_id(self):
while True:
self.id +=1
yield self.id
def tok(self):
a = self.gen_id()
return next(a)
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 2 years ago.
Improve this question
I initialised weatherreport.Weather to self.weather in the main file which is responsible for my basic main window.
See the image [![here][1]][1]
def __init__(self):
self.root = tk.Tk()
#Initialize Weather module
self.weather = weatherreport.Weather()
def show_weather(self):
city_name = tk.Entry(self.root, text = "Enter city name : ", width = 15)
self.weather(city_name)
def __init__(self, city):
self.base_url = "http://api.openweathermap.org/data/2.5/weather?"
self.city = city```
U can clearly come to know what error I'm facing. I searched all over internet or atleast what i can. None explains this. I'd love to rectify this but i need some help here. It is a small side project for my internals.
Thanking you in anticipation
[1]: https://i.stack.imgur.com/KLRqQ.png
Welcome to Stack Overflow. Please remember to paste code instead of images of code so it is easier to help you.
Your error is a simple and self-explanatory one. The error is: TypeError: __init__() missing 1 required positional argument: 'city'. Let's break it down.
__init__() is a special function of classes in Python, sometimes called the "constructor". This function gets called when you create an "instance" or "object" of that class.
For example, if I have the following dummy class:
class Foo:
def __init__(self):
print("bar")
When I create an instance of Foo by doing something like x = Foo(), then __init__() gets called and I should see "bar" get printed before the assignment happens.
The error is telling us that this special function of the Weather class is expecting an argument, but never got it. If you look at the __init__ function for the Weather class, you will see that it takes in a parameter called "city".
So to fix this, you have to give provide the arguments to __init__ when creating your class. Something like
self.weather = weatherreport.Weather("Detroit")
I can't really see the error properly, you should post the error and the code as text and not as an picture.
But your __init__ calls two arguments. self and city.
So you should inicialize it with those two arguments. From the error it seems like you only have 1 argument in the function.
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.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I have this problem I am trying to solve:
Write the definition of a class ContestResult containing:
•An instance variable winner of type String , initialized to the empty String.
•An instance variable second_place of type String , initialized to the empty String.
•An instance variable third_place of type String , initialized to the empty String.
•A method called set_winner that has one parameter, whose value it assigns to the instance variable winner .
•A method called set_second_place that has one parameter, whose value it assigns to the instance variable second_place .
•A method called set_third_place that has one parameter, whose value it assigns to the instance variable third_place .
•A method called get_winner that has no parameters and that returns the value of the instance variable winner .
•A method called get_second_place that has no parameters and that returns the value of the instance variable second_place .
•A method called get_third_place that has no parameters and that returns the value of the instance variable third_place .
This is my code:
class ContestResult():
def __init__(self):
self.winner= ""
self.second_place= ""
self.third_place= ""
def set_winner(self,value):
self.winner= value.set_winner
def set_second_place(self,value):
self.second_place= value_set_second_place
def set_third_place(self,value):
self.third_place= value.set_third_place
def get_winner(self):
return self.winner
def get_second_place(self):
return self.second_place
def get_third_place(self):
return self.third_place
I am receiving this error:
Exception occurred(<class 'AttributeError'>, AttributeError("'str' object has no attribute 'set_winner'",)
Can someone help me with this? Please and thank you.
One are passing in a string to set_winner. That is why you're seeing the error.
However, you don't need to create the set_winner and get_winner functions in Python. All of the object's member variables, in this case winner, second_place and third_place, are publicly accessible. If you really want to have mutators and accessors, the Pythonic way of doing so is with property:
class ContestResult(object):
def __init__(self):
self.__winner = ''
#property
def winner(self):
return self.__winner
#winner.setter
def winner(self, value):
print "I'm about to set the value of winner"
self.__winner = value
and now when you want to see the "winner" property:
foo = ContestResult()
foo.winner = "Frank"
it works just like a regular member variable.
in def set_winner(self,value), presumably value is a string, right? Why are you calling value.set_winner?
self.winner = value
Note that this is true for all your set_s.
You really don't need all that with Python unless you're trying to modify the way attributes are actually get and set.
class ContestResult(object):
def __init__(self, winner, second_place, third_place):
self.winner = winner
self.second_place = second_place
self.third_place = third_place
Stick = ContestResult("Foo", "Bar", "Eggs")
Stick.second_place #gets "Bar"
Stick.winner = "Clown" #sets Stick.winner
Python isn't Java :) you don't need those methods -- again, unless you're going to be modifying the data or decorate the method or something. In which case you can use the #property syntax as outlined by wheaties -- and in doing so, you still don't actually call the get or set methods, you just interact in a Pythonic way and use assignment.
Stick.second_place = "Earl" #this will call the property setter