Static Methods in Python - python

I am trying to simulate the rolling of a die and have used this code
class dicesimulator:
def __init__(self, list = [0,0,0,0,0,0]):
self.list = list
#staticmethod
def diceroller():
outcome = random.randit(0,5)
print outcome + 1
mydice = dicesimulator()
print mydice.diceroller
However when I run the code it returns rather then a number. Why is this happening. Also as far as I am aware I should also be able to call the class itself on a static method ie dicesimulator.diceroller. However, it also returns

So there's a couple of issues. Firstly, there's not really a terribly good reason to use static methods. It's essentially no different than just making a function. Secondly, you aren't actually returning the number from within your diceroller() method. Thirdly, you aren't actually calling diceroller because you forgot to put parens so instead you're just printing the function directly (the string representation of it).

You forgot the parens.
mydice.diceroller()

I'm glad you found the indentation repair.
(1) You asked for the diceroller object, rather than calling the method.
(2) There is no "randit". Try "randint".
import random
class dicesimulator:
def __init__(self, list = [0,0,0,0,0,0]):
self.list = list
This yields output
6
None
Note that you have not returned anything from the function diceroller. You also haven't used dicesimulator.list for anything yet.
Consider searching the internet for implementations.

There's no need to complicate things by unnecessarily using classes and static methods.
from random import randint
print(randint(1,6))

Related

Is it a bad programing practice to put a function inside a class method?

I'm looking at a case like this:
def parse_item(self, response):
item = MetrocItem()
def ver(string):
if string:
return string
else:
return 'null'
item['latitude'] = ver(response.xpath('//input[#id="latitude"]/#value').extract_first())
It works, but is there a better way to do this?
As #Graipher mentioned in the comments, this is certainly valid in some cases, but in your particular case, it is unnecessary. If your function depends on a local variable, then you're returning a closure that needs to be reconstructed every time you call the method. But in your case, the function is going to behave the same way every time you call the method, so it would make more sense to define it globally as a private method, or even as a lambda in your case.
ver = lambda x: x if x else 'null'
But the preferred approach would be to simply define it globally and start the name with an underscore to make the intention clear.
def _ver(string):
...
You can get rid of that function completely:
string = response.xpath('//input[#id="latitude"]/#value').extract_first()
item['latitude'] = string if string else 'null'
There are use cases for having a local function - either in a class method or other method, say if you want a closure capturing something local.
In you case you want something like a colasecing null:
e.g.
>>> s = None
>>> s or "None"
'None'
So, you can use
item['latitude'] = response.xpath('//input[#id="latitude"]#value').extract_first() or "null"
It is not bad practice, but here's an alternative.
Since this small function doesn't depend on anything in parse_item and you might want it to be constructed only once, for performance, you could do this:
def parse_item(self, response):
...
def _ver(string):
...
parse_item.ver = _ver
del _ver
and refer to it inside parse_item as parse_item.ver instead of just ver. This avoids cluttering the global namespace, even with an underscored method that Python partially hides for you.
I would have recommended the lambda expression as another alternative, but Silvio got to it first.
Also, the comments that it could be a global function, visible to all, only makes sense if there's any chance it might be used anywhere else.
Also also, you can eliminate this example completely, as doctorlove and Niklas have suggested, but I assume that you mean this as an example of more complex cases.
I guess parse_item is a method inside your class. Then you can use Python's "private" methods to make your code more readable and cleaner.
Check how to write Python "private" method and then check why it's not actually a private method. ;)

returning functions from a method in python

I have tried looking into the documentation and google search , but I am unable to find out the significance of the [clazz] at the end of method. Could someone help me understand the meaning of the [clazz] at the end of the method? Thanks.
def get_context_setter(context, clazz):
return {
int: context.setFieldToInt,
datetime: context.setFieldToDatetime
}[clazz]
setFieldToInt and setFieldToDatetime are methods inside context class.
This function returns one of two things. It returns either context.setFieldToInt or context.setFieldToDatetime. It does so by using a dictionary as what would be a switch statement in other programming languages.
It checks whether clazz is a reference to the class int or a reference to the class datetime, and then returns the appropriate method.
It's identical to this code:
def get_context_setter(context, clazz):
lookup_table = {int: context.setFieldToInt,
datetime: context.setFieldToDatetime
}
context_function = lookup_table[clazz] # figure out which to return
return context_function
Using a dict instead of a switch statement is pretty popular, see Replacements for switch statement in Python? .
More briefly.
The code presented is expecting the class of some object as a parameter poorly named as clazz.
It's then using that class as a dictionary key.
They're essentially trying to accept two different types and call a method on the object type.
class is a keyword in Python.
The author of the code you show chose to use a strange spelling instead of a longer snake_case parameter name like obj_class.
The parameters really should have been named obj, obj_class
Or
instance, instance_class
Even better, the class really need not be a separate parameter.

AttributeError: instance has no attribute

This seems to be a common error in Python, and I've found many instances of people asking about similar but spent the last (long amount of time) trying those solutions where they seemed applicable and have had no luck, so resorting to asking to find out what I'm missing.
I'm receiving AttributeError: WebHandler instance has no attribute 'search_str'
It seems to be this one particular method, any time I call any of the class variables set in ___init___ from this method I receive this error. I've extracted it to a test file as a simple function rather than a class method and it works fine, and I've tried re-indenting everything a few times to make sure it wasn't that, so I'm at a loss on this.
I'm using Python 2.7 and TextWrangler if either of these are helpful (TextWrangler hasn't given me any problems in 3 years like this, but figured anything should be included)
import requests
import re
class WebHandler():
def ___init___(self):
self.urllist = []
self.search_str = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_#.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', re.I|re.M)
def set_urls(self, test, data):
for line in test[11:]:
if (("even" in line) or ("odd" in line)):
match = re.search(self.search_str, line)
self.urllist.append(match.group(0))
Another thing I tried, if I copy the attributes from ___init___ and simply make them local to set_urls() and call them without self that way it works properly and doesn't throw any errors, which is confusing me even more.
No idea what I'm missing. Thanks!
Your init function has three underscores:
def ___init___(self):
It should have only two:
def __init__(self):
As it is written now, it is not being called when you create a new object.
This that you have:
def ___init___(self):
Is not the same as this that gets called when an object is instantiated:
def __init__(self):
The difference is that you have three underscores on either side of init, while two are required.

How to add arguments next to 'self' in a python function?

I'm trying to fix up a little program, but looks like I'm in a bit over my head. The whole code is too long to copy here, so I'm just gonna paste the problematic part.
def kontroll(self):
count=IntVar()
sisend=sisendivaartus.get()
print(count)
if count==1:
kast.delete(0.0,END)
sisend.delete(0.0,END)
count=0
else:
kast.delete(0.0,END)
if sisend=="õige" or sisend=="ÕIGE" or sisend=="Õige":
if oige==sonake:
if tahendus==" ":
kast.insert(END,"Tubli, õige!"+"\n"+str(oige)+"\n"+str(tahendus))
count=1
else:
kast.insert(END,"Tubli, õige!"+"\n"+str(oige)+"\n:"+str(tahendus))
count=1
#skoor+=1
#skoor=skoor+1
else:
if tahendus==" ":
kast.insert(END,"Kahjuks eksid. Õige on "+str(oige)+"\n"+str(tahendus))
count=1
else:
kast.insert(END,"Kahjuks eksid. Õige on "+str(oige)+":\n"+str(tahendus))
count=1
#vale=vale+1
#skoor=skoor-1
else:
if sisend==oige:
if tahendus==" ":
kast.insert(END,"Tubli, õige!\n"+str(oige)+"\n"+str(tahendus))
count=1
else:
kast.insert(END,"Tubli, õige!\n"+str(oige)+":\n"+str(tahendus))
count=1
#skoor=skoor+1
else:
if tahendus==" ":
kast.insert(END,"Kahjuks eksid. Õige on "+str(oige)+"\n"+str(tahendus))
count=1
else:
kast.insert(END,"Kahjuks eksid. Õige on "+str(oige)+":\n"+str(tahendus))
count=1
#vale=vale+1
#skoor=skoor-1
#if skoor<0:
# skoor=0
Now the problem is that I have to add arguments to kontroll() but I don't know how to do that with 'self' being there. To be honest, I don't even understand why I need that 'self' there, 'cause I'm not using classes which usually use the 'self' argument... So anyway, I googled the error I recieved without having 'self' there and after adding 'self' it started working, but I can't add 'skoor' and 'vale' in brackets...
Right now I just start kontroll with nothing in brackets, like this: kontroll().
So how should I start the function and how should I add the arguments to it? I can't use global variables either, 'cause this 'skoor=skoor+1' messes everything up (can't have global variable on the left side of equals sign).
Thanks.
EDIT:
GUI part of my program looks like this:
raam=Tk()
raam.title("MÄNG")
raam.geometry("430x450")
valik=IntVar()
valik2=IntVar()
C2=Checkbutton(raam,text="f",variable=valik2,command=lambda:ok.config(state=ACTIVE)).place(x=5,y=10)
ok=Button(raam,text="Alusta!",command=alusta,state=DISABLED)
ok.place(x=230,y=20,width=80)
C1=Checkbutton(raam,text="š",variable=valik,command=lambda:ok.config(state=ACTIVE)).place(x=5,y=30)
sisendivaartus=StringVar()
sisend=Entry(raam,textvariable=sisendivaartus)
sisend.place(x=10,y=250,width=200)
sisend.bind("<Return>",kontroll(skoor,vale))
credit=Label(raam,text="2013",font=("Verdana","7"))
credit.place(x=0,y=430)
score=Label(raam,text="Skoor:",font=("Verdana","7"))
score.place(x=380,y=430)
nupp=Button(raam,text="Seaded",command=seaded)
nupp.config()
nupp.place(x=330,y=20,width=80)
kast=Text(raam,wrap=WORD,font=("Verdana",10))
kast.config()
app=App(raam)
kast.place(x=10,y=60,width=400,height=180)
raam.mainloop()
For Henry's suggestion (how to use the function when not in class), I start getting different errors that have no basis, for example "NameError: global name 'oige' is not defined". Despite what the error says, global name 'oige' is defined and works fine without arguments. If I replace 'skoor' and 'vale' in the functions definition with just 'self' and recall it without any arguments, everything works just fine. I guess this is kind of hard to understand without seeing the whole piece, so I uploaded it here, if anyone has a minute.
PS. what I said earlier about having 0 classes in my code - that has changed since I constantly keep working on this. Also please keep in mind that this is a beta version of a beta, so many things are not supposed to work yet.
(For trivia: it tests and trains person's capabilities in Estonian orthography)
Writing Your Function
It's very easy to add more arguments to a function; simply change your function definition to
def kontroll(self, skoor, vale):
# Your code here.
Then skoor and vale become variable names local to the kontroll function and you can use them like any other variable.
As to why you need self in the function definition, that's because (presumably) this method is actually an instance method of some class you've defined. Instance methods always receive the object they're bound to as their first argument. This argument is called self, which is why you have to have an argument reserved for it. See this question for a more complete explanation.
If this is not actually an instance method of some class, mind you, then you don't actually need self. And generally speaking, if the method doesn't need a reference to a specific object instance, then there's no reason to make it an instance method!
Calling Your Function
Calling your function is just as simple, but it depends on the answer to the other question: is this actually an instance method? If it's defined inside a class (which it sounds like it is) then you need to do something like the following:
class C(object):
def kontroll(self, skoor, vale):
pass # Your code goes here.
c = C() # Create an instance of the class!
c.kontroll(skoor, vale) # The instance (c) is automatically passed to the method.
If, on the other hand, your function is not defined inside a class, your code should look like this:
def kontroll(skoor, vale):
pass # Your code goes here.
kontroll(skoor, vale)
You need self because this is almost certainly a method of a class, and you need to pass the object to the method when it is called. Self is just a convention, technically you can use some other name for this just as easily. That being said, it seems like you need to do some reading about classes in python and really try to understand the way an object instance works. I recommend starting with the docs:
http://docs.python.org/2/tutorial/classes.html
There appear to be a lot of globals in your code snippet that should probably be class variables, and you really need to understand how things like the __init__ method work before going to deep into this.

Overwriting class methods without inheritance (python)

First, if you guys think the way I'm trying to do things is not Pythonic, feel free to offer alternative suggestions.
I have an object whose functionality needs to change based on outside events. What I've been doing originally is create a new object that inherits from original (let's call it OrigObject()) and overwrites the methods that change (let's call the new object NewObject()). Then I modified both constructors such that they can take in a complete object of the other type to fill in its own values based on the passed in object. Then when I'd need to change functionality, I'd just execute myObject = NewObject(myObject).
I'm starting to see several problems with that approach now. First of all, other places that reference the object need to be updated to reference the new type as well (the above statement, for example, would only update the local myObject variable). But that's not hard to update, only annoying part is remembering to update it in other places each time I change the object in order to prevent weird program behavior.
Second, I'm noticing scenarios where I need a single method from NewObject(), but the other methods from OrigObject(), and I need to be able to switch the functionality on the fly. It doesn't seem like the best solution anymore to be using inheritance, where I'd need to make M*N different classes (where M is the number of methods the class has that can change, and N is the number of variations for each method) that inherit from OrigObject().
I was thinking of using attribute remapping instead, but I seem to be running into issues with it. For example, say I have something like this:
def hybrid_type2(someobj, a):
#do something else
...
class OrigObject(object):
...
def hybrid_fun(self, a):
#do something
...
def switch(type):
if type == 1:
self.hybrid_fun = OrigObject.hybrid_fun
else:
self.fybrid_fun = hybrid_type2
Problem is, after doing this and trying to call the new hybrid_fun after switching it, I get an error saying that hybrid_type2() takes exactly 2 arguments, but I'm passing it one. The object doesn't seem to be passing itself as an argument to the new function anymore like it does with its own methods, anything I can do to remedy that?
I tried including hybrid_type2 inside the class as well and then using self.hybrid_fun = self.hybrid_type2 works, but using self.hybrid_fun = OrigObject.hybrid_fun causes a similar error (complaining that the first argument should be of type OrigObject). I know I can instead define OrigObject.hybrid_fun() logic inside OrigObject.hybrid_type1() so I can revert it back the same way I'm setting it (relative to the instance, rather than relative to the class to avoid having object not be the first argument). But I wanted to ask here if there is a cleaner approach I'm not seeing here? Thanks
EDIT:
Thanks guys, I've given points for several of the solutions that worked well. I essentially ended up using a Strategy pattern using types.MethodType(), I've accepted the answer that explained how to do the Strategy pattern in python (the Wikipedia article was more general, and the use of interfaces is not needed in Python).
Use the types module to create an instance method for a particular instance.
eg.
import types
def strategyA(possible_self):
pass
instance = OrigObject()
instance.strategy = types.MethodType(strategyA, instance)
instance.strategy()
Note that this only effects this specific instance, no other instances will be effected.
You want the Strategy Pattern.
Read about descriptors in Python. The next code should work:
else:
self.fybrid_fun = hybrid_type2.__get__(self, OrigObject)
What about defining it like so:
def hybrid_type2(someobj, a):
#do something else
...
def hybrid_type1(someobj, a):
#do something
...
class OrigObject(object):
def __init__(self):
...
self.run_the_fun = hybrid_type1
...
def hybrid_fun(self, a):
self.run_the_fun(self, a)
def type_switch(self, type):
if type == 1:
self.run_the_fun = hybrid_type1
else:
self.run_the_fun = hybrid_type2
You can change class at runtime:
class OrigObject(object):
...
def hybrid_fun(self, a):
#do something
...
def switch(self):
self.__class__ = DerivedObject
class DerivedObject(OrigObject):
def hybrid_fun(self, a):
#do the other thing
...
def switch(self):
self.__class__ = OrigObject

Categories