I'm trying to append data to a list but right before I append a new value the list seems to reset. Here's the relevant code:
This is the main module:
def update():
global url
data.add_price(df.pulldata(url))
This is the data module:
historical_price = []
def add_price(price):
historical_price.append(price)
print(historical_price)
I am guessing that the problem is the fact that I am defining historical_price to be empty at the top. This however confuses me, since that whole script is never run. How do I go about fixing this? Hints are appreciated.
You never instantiate the data class, so it's performing add_price without an instance to perform it on. You should add self as a parameter to add_price and you should instantiate your data class something like this.
d = data()
def update():
global url
d.add_price(df.pulldata(url))
You should also make historical_price an attribute of the data class, so the data class should look something like this.
class data:
def __init__(self):
self.historical_price = []
def add_price(self, price):
self.historical_price.append(price)
print(self.historical_price)
Since your add_price function is in a different module, this part historical_price = [] is run everytime you invoke that method.
Invoking a global function executes all global code first, then executes the function.
To fix this, you could:
Write a class with that list as an instance variable and instantiate it in your main code.
Write that class and make the method static, using the list as a class variable.
Define the gobal variable in your main code and hand it to the function as a parameter.
The main code is the top level code that controls the flow of the program by invoking methods and instantiating classes.
Related
i created this class for my homework:
class sayfa():
isim=" "
def __init__(self,bSayisi,ySayisi,pSayisi,iSayisi,tSayisi):
self.bSayisi=bSayisi
self.ySayisi=ySayisi
self.pSayisi=pSayisi
self.iSayisi=iSayisi
self.tSayisi=tSayisi
if ((((bSayisi+ySayisi+pSayisi)/iSayisi)/tSayisi)*100)>0.2:
print(isim,"başarılı")
else:
print(isim,"başarısız")
then i called it in another .py file:
from eRate import sayfa
ybs1=sayfa(365000,65000,870,500,1125000)
ybs1.isim="YBS-1"
then i tried to work it and it gave me this error:
NameError: name 'isim' is not defined
I think i did something wrong when i'm writing class but i don't know what i actually done wrong.Can you help me?
edit:
My code worked when i put isim variable in def init but it looks weird.It looks like this:
class sayfa():
def __init__(self,bSayisi,ySayisi,pSayisi,iSayisi,tSayisi,isim):
self.isim=str(isim)
self.bSayisi=bSayisi
self.ySayisi=ySayisi
self.pSayisi=pSayisi
self.iSayisi=iSayisi
self.tSayisi=tSayisi
if ((((bSayisi+ySayisi+pSayisi)/iSayisi)/tSayisi)*100)>0.2:
print(isim,"başarılı")
else:
print(isim,"başarısız")
and when i'm adding data in class it gets weirder:
from eRate import sayfa
ybs1=sayfa(365000,65000,870,500,1125000,"YBS-1")
The error isn't with the way you're assigning things, but with the way you're accessing them.
Just as you have to do self.bSayisi to set an attribute, you have to do self.isim to access one. So:
print(self.isim, "başarılı")
(and the same for the other line…)
If you're wondering why you were able to access other values like bSayisi without self.bSayisi—that's just because you happen to have a parameter named bSayisi that happens to have the same value as self.bSayisi (because you just made that true a few lines earlier). If you changed it to, say, self.bSayisi = bSayisi*2, or you renamed the parameter to myBSayisi and did self.bSayisi = myBSayisi, you'd see that just using bSayisi instead of self.bSayisi was no longer correct.
However, while this eliminates the error, I'm not sure it actually does what you want. At the time you're doing this print, you haven't assigned an isim value to the object yet, so it's going to get the class value as a default, so it's always just going to be " ". Is that really what you wanted?
If not, you need to move the print calls to some other method that you can call later, after having assigned isim. For example:
class sayfa():
isim=" "
def __init__(self,bSayisi,ySayisi,pSayisi,iSayisi,tSayisi):
self.bSayisi=bSayisi
self.ySayisi=ySayisi
self.pSayisi=pSayisi
self.iSayisi=iSayisi
self.tSayisi=tSayisi
def displaystuff(self):
if ((((self.bSayisi+self.ySayisi+self.pSayisi)/self.iSayisi)/self.tSayisi)*100)>0.2:
print(self.isim,"başarılı")
else:
print(self.isim,"başarısız")
ybs1=sayfa(365000,65000,870,500,1125000)
ybs1.isim="YBS-1"
ybs1.displaystuff()
Of course moving the isim into the constructor works, by avoiding the problem you were running into. It's not an answer to how to add data after the __init__ method, of course, because you're instead adding the data in the __init__ method. When that's appropriate, it's the simplest answer.
But if it looks weird in this case (I'll take your word for it; I don't know exactly what this code is trying to do), it's probably the wrong answer for this particular class.
In which case, you do need to know how to add data after the __init__ method, as you asked. Or, rather, you need to know how to access that data—because you were already adding it correctly.
This is the difference between class attributes (when it is outside of the __init__ with no self.) and instance attributes (when you added it inside the __init__ with the self.).
Class attributes are a little more complicated since they pertain to all the instances of that class (you could overwrite them within some instances, but then they'd become instance attributes in those cases)... and so if you changed a class attribute, it would affect all other instances you may have created or will create in the future.
For a more in-depth discussion of class attributes vs instance attributes see this answer that summarizes this post.
Normall __init__(..) is used to initialize / instantiate your instance. I would not print in it, nor calculate (unless you calculate some other class-variables and set them).
You need to prefix your variables of the instance by self. and the static class variable with the class name to acess it:
class sayfa():
isim=" " # this is a shared class variabl (aka static)
def __init__(self,bSayisi,ySayisi,pSayisi,iSayisi,tSayisi):
self.bSayisi=bSayisi # these are all instance variables, not shared
self.ySayisi=ySayisi
self.pSayisi=pSayisi
self.iSayisi=iSayisi
self.tSayisi=tSayisi
self.unusedSum = ySayisi + pSayisi + iSayisi
def printMe(self): # lookup __str__() and __repr__() for how to output your instance
if ((((self.bSayisi+self.ySayisi+self.pSayisi)/self.iSayisi)/self.tSayisi)*100)>0.2:
print(sayfa.isim,"some text") # use the static class variable
else:
print(sayfa.isim,"some other text")
sayfa.isim = "Coffee " # you set static class variables by prefixing class name
my_sayfa_instance = sayfa(365000,65000,870,500,1125000)
other_sayfa_instance = sayfa(3600,65000,870,500,10)
my_sayfa_instance.printMe()
other_sayfa_instance.printMe()
Output:
Coffee some other text
Coffee some text
I have a file called file_parsers.py and it contains the following class:
class FileParser():
def __init__(self, file_text):
self.file_text = file_text
def do_something(self):
my_value = func_with_no_state()
I'm not sure what questions to ask when deciding whether func_with_no_state() should be inside the class or outside of the class as a file-level function?
Also, is it easier to stub this function when it is at a file-level or inside the class?
So... Does any other class use func_with_no_state? If not, it should be hidden within FileParser. If something else does use it, you have a bigger question. If OtherClass uses func_with_no_state pretty frequently (on par with FileParser) then it would be a good idea to keep func_with_no_state outside so that both classes can use it. But if FileParser is by far the main user, then OtherClass could just pull the function from FileParser's definition.
I'm trying to use the ui object within the Pawn class and I define and initiate ui outside everything, so it is global right? I've looked on here for questions relating to using variables outside classes but they seem to all refer to .self which I used in the UI class when initiating the Chess object.
The # represent bits of code I've cut out to help readability.
class UI:
def ___init__(self):
self.chess = Chess()
# Calls main menu function which goes to a new game option
def newGame(self):
self.chess.startGame()
while len(self.chess.pieces[0] == 2): # Which is index for Kings
# Game, which is where *move* is called
class Chess:
def startGame(self):
self.chessBoard = Grid(9,9)
self.pieces = []
self.pawns = []
for i in range(8):
self.pawns.append(PawnObject(x,y,side))
self.pieces.append(self.pawns)
class Grid:
# Init method
def cellOccupied(self,x,y):
# This function checks if a place is empty
# If empty, return false else, true
class Object:
# Sets x, y, width, height
class ChessPiece:
# Child of Object sets side (black or white)
class PawnObject:
def move(self,newX,newY):
if ui.chess.chessBoard.cellOccupied(newX,newY) == False:
# Move
# More code
ui = UI()
Traceback: https://gyazo.com/33e5b37b5290ff88433b29874c117ad7
Am I doing something blindingly wrong? I think the way I've programmed this all is very inefficient as I am still learning so is this a result of that? Thank you.
The problem is that this cascading series of events all happens inside the initialisation function for UI; one class calls the next, all before the original __init__ has had a chance to return. This means that the line that did that initialisation has not completed, so the ui variable does not exist yet.
You should try and move some of this out of that cascade. In particular, I can't see why the pawns should move as a result of initialising the UI class; that doesn't seem to make sense at all.
You should also consider why you need ui to be a global variable; seems more likely that it should be an attribute of one of the classes, perhaps Grid, and the pawn can reference it via that instance.
You're probably using ui in the body of a class, which is executed the moment the interpreter sees the class (and therefore before ui exists). You can only use it inside methods or functions since those are only executed when they're called. In other words:
class UI:
def open(self):
pass
class Chess:
ui.open() # <--- this causes an error because it happens before the last line does
def startGame(self):
ui.open() # <--- this is OK
ui = UI()
Also, I think your message indicates that you wrote global ui somewhere which is only necessary if you're planning on assigning a new value to ui, i.e. ui = something. If you just want to use it, e.g. ui.open(), you don't need the global declaration. But removing it won't solve your problem.
You also need to correct
chessBoard = Grid(9,9)
to
self.chessBoard = Grid(9,9)
to make chessBoard an attribute of Chess, which you need to be able to say ui.chess.chessBoard.
here is a part of my code :
class projet(object):
def nameCouche(self):
valLissage = float(ui.valLissage.displayText())
return (valLissage)
valCouche = nameCouche() # asks for a positional argument but 'self' doesnt work
def choixTraitement(self):
ui.okLissage.clicked.connect(p.goLissage)
def goLissage(self, valCouche):
if ui.chkboxLissage.isChecked():
print(valCouche) # result is False
os.system(r'"C:\Program Files\FME\fme.exe" D:\Stelios\..... --MAX_NUM_POINTS {0}'.format(valCouche))
So I would like to use valCouche in goLissage method but it doesnt work.
I thought that valCouche would have the argument of valLissage but instead it gives False as a value.
I've tried different alternatives but still doesnt work.
You've got multiple problems here.
First, if you write this in the middle of a class definition:
valCouche = nameCouche()
... you're creating a class attribute, which is shared by all instances, not a normal instance attribute.
Also, you're running this at class definition time. That means there is no self yet--there aren't any instances yet to be self--so you can't call a method like nameCouche, because you don't have anything to call it on.
What you want to do is call the method at instance initialization time, on the instance being initialized, and store the return value in an instance attribute:
def __init__(self):
self.valCouche = self.nameCouche()
Then, when you want to access this value in another method later, you have to access it as self.valCouche.
If you make those changes, it will work. But your object model still doesn't make much sense. Why is nameCouche a method when it doesn't have anything to do with the object, and doesn't access any of its attributes? Maybe it makes sense as a #staticmethod, but really, I think it makes more sense just as a plain function outside the class. In fact, none of the code you've written seems to have anything to do with the class.
This kind of cram-everything-into-the-class design is often a sign that you're trying to write Java code in Python, and haven't yet really understood how Python does OO. You might want to read a good tutorial on Python classes. But briefly: if you're writing a class just to have somewhere to dump a bunch of vaguely-related functions, what you want is a module, not a class. If you have some reason to have instances of that class, and the functions all act on the data of each instance, then you want a class.
You have to declare variabile in the __init__ method (constructor) and then use it in your code
ex:
class projet(object):
def __init__(self):
self.valCouche = ''
def nameCouche(self):
valLissage = float(ui.valLissage.displayText())
return (valLissage)
def choixTraitement(self):
ui.okLissage.clicked.connect(p.goLissage)
def goLissage(self, valCouche):
if ui.chkboxLissage.isChecked():
self.valCouche = self.nameCouche()
print(self.valCouche) # result is False
os.system(r'"C:\Program Files\FME\fme.exe" D:\Stelios\..... --MAX_NUM_POINTS {0}'.format(self.valCouche))
you have to define an initialization function: def__init__(self)
defining valCouche as an instance attribute make it accessible on all the method so we have the following
class projet(object):
def __init__(self):
self.valCouche = ''
def nameCouche(self):
self.valCouche = float(ui.valLissage.displayText())
#staticmethod #here there is no need for self so it is a method of class
def choixTraitement():
ui.okLissage.clicked.connect(p.goLissage)
def goLissage(self):
if ui.chkboxLissage.isChecked():
print(self.valCouche) # result is False
os.system(r'"C:\Program Files\FME\fme.exe" D:\Stelios\..... --MAX_NUM_POINTS {0}'.format(self.valCouche))
I'm trying to modify class attribute by reference to object in __init__ method and then use it in another method. Sadly the following code sample doesn't work as expected...
CODE
class Translator:
#list of attributes
parser=None
def __init__(self):
parser = Parser_class() ...
#some other commands
def Translate(self):
something=self.parser.GenerateHead() ...
#more commands
COMPILE ERR
AttributeError: 'NoneType' object has no attribute 'GenerateHead'
I know that I can give it to the Translate method as argument, I'm just curious why this statement within Python doesn't work.
You're doing your instance attributes wrong.
First off, you don't need to declare your attributes ahead of time. Putting parser = None at the top level of the class creates a class variable named parser, which I don't think is what you want. Usually in Python you can add new instance attributes at any time by a simple assignment: instance.attr = "whatever".
Second, when you want to do an instance assignment from within a method, you need to use self to refer to the instance. If you leave off self, you'll be assigning to a local variable inside your function, not to an instance or class variable. Actually, the specific name self isn't necessary, but you do need to use the first argument to the method (and it's probably not a good idea to break the convention of naming that self).
So, to fix your code, do this:
class Translator:
# don't declare variables at class level (unless you actually want class variables)
def __init__(self):
self.parser = Parser_class() # use self to assign an instance attribute
def Translate(self):
something = self.parser.GenerateHead() # this should now work