how to make a function work in python - python

I wrote the following code in python and it works fine until I try to make it a function, can anyone help?
import random
def club():
members=int(input("members"))
print (random.randint(1, members))

You have to use 4 spaces ( or tab) per indentation level. And call the function of course.
import random
def club():
members=int(input("members"))
print (random.randint(1, members))
club()

members is local to the club function, thus not visible to your print call

members is considered to be a local variable within the club function. If you want to use it, you can return it. You can do something like this:
import random
def club():
members = int(input("Members: "))
return members
print(random.randint(1, club()))
Also, since Python is an Object-Oriented Language, you can set the value that club returns to a variable (or anything for that matter):
a = club() # Then a might be 5
b = random.randint(1, a)
And then use that variable elsewhere:
print(b)

Related

How to use dictonary to create an object?

I'm new in stackoverflow and I'd like to make my first question for a problem in this code I've tried to write to learn objects in python.
I'm trying to call the creation of an object through a dictionary.
My purpose is to create an object thanks to a number, for example I have the dictionary newch = {1 : Character.new_dragon(), 2 : Character.new_goblin()} and when I call Player1 = newch[1] it should create a new dragon (#classmethod new_dragon) and assign it to Player1
The problem is that when i run the program, Character.new_dragon() and Character.new_goblin() are called automatically (i put a control print), but when I write "DRAGO" after the request "which player?" the functions aren't called because there isn't the control print
import random
class Character:
def __init__(self,idd,height,weight,att,defe):
self.idd=idd
self.height=height
self.weight=weight
self.att=att
self.defe=defe
#classmethod
def new_goblin(cls):
print('newgoblin')
return cls(1,getr(1,1.5,0.1),getr(40,60,0.5),getr(5,15,1),getr(6,10,1))
#classmethod
def new_dragon(cls):
print('newdrago')
return cls(2,getr(20,30,1),getr(500,2000,5),getr(50,150,3),getr(20,100,3))
def getr(start,stop,step): #returns float
x=random.randint(1, 1000)
random.seed(x)
return random.randint(0, int((stop - start) / step)) * step + start
play={1:'p1', 2:'p2', 3:'p3', 4:'p4'} #dict for players
newch={1:Character.new_dragon(),2:Character.new_goblin()} ############This doesn't work
i=1
while True:
char=input("which player? Drago or Goblin?").upper()
if(char=="DRAGO"):
play[i]=newch[1] #here i try to call Character.new_dragon()
i+=1
break
elif(char=="GOBLIN"):
play[i]=newch[2]
i+=1
break
print("write \'Drago\' or \'Goblin\'")
print(play[1].height, play[1].weight, play[1].att, play[1].defe)
Here's my code, if you could help me, I would be very glad, thanks
The new object is created immediately when you call Character.new_dragon(), and the object is then stored in the dict.
Instead you could not store the object in the dict, but the function that creates it. That function would be Character.new_dragon (without the ()). Then you can call that function when the player selects a character:
play[i]=newch[1]()
Complete code:
import random
class Character:
def __init__(self,idd,height,weight,att,defe):
self.idd=idd
self.height=height
self.weight=weight
self.att=att
self.defe=defe
#classmethod
def new_goblin(cls):
print('newgoblin')
return cls(1,getr(1,1.5,0.1),getr(40,60,0.5),getr(5,15,1),getr(6,10,1))
#classmethod
def new_dragon(cls):
print('newdrago')
return cls(2,getr(20,30,1),getr(500,2000,5),getr(50,150,3),getr(20,100,3))
def getr(start,stop,step): #returns float
x=random.randint(1, 1000)
random.seed(x)
return random.randint(0, int((stop - start) / step)) * step + start
play={1:'p1', 2:'p2', 3:'p3', 4:'p4'} #dict for players
newch={1:Character.new_dragon,2:Character.new_goblin} ############This doesn't work
i=1
while True:
char=input("which player? Drago or Goblin?").upper()
if(char=="DRAGO"):
play[i]=newch[1]() #here i try to call Character.new_dragon()
i+=1
break
elif(char=="GOBLIN"):
play[i]=newch[2]()
i+=1
break
print("write \'Drago\' or \'Goblin\'")
print(play[1].height, play[1].weight, play[1].att, play[1].defe)
This works, however I would not say it is the best coding style. Its hard to judge from only this piece of code, but it might be a better idea to make Drago and Goblin subclasses of the Character class and store the type of those classes in that dictionary.
newch={1:Character.new_dragon(),2:Character.new_goblin()}
As this is written, the new_dragon and new_goblin functions are called when the dictionary is created. This is why you are seeing them both run "automatically" every time you run your program.
If you instead declared the dict like:
newch={1:Character.new_dragon ,2:Character.new_goblin}
And later have something like:
if(char=="DRAGO"):
play[i]=newch[1]()
(note the parenthesis after the newch[1]) you should get what you want.
Incidentally, those break statements aren't necessary. The If/elif/else chain doesn't fall through like a switch statement in other languages.
When you are initialising the dictionary this way:
newch={1:Character.new_dragon(),2:Character.new_goblin()}
You are binding keys (1 and 2) to the return values of the new_dragon and new_goblin functions. You need to bind the functions(without calling them) like so:
newch={1:Character.new_dragon,2:Character.new_goblin}
Notice there are no brackets!
And then, when you create players, you execute those functions like so:
play[i]=newch[1]() Notice here we have brackets!
Additionally, if I may suggest an improvement of the code here:
if(char=="DRAGO"):
play[i]=newch[1]()
i+=1
To avoid the if statement, you can create you mapping with a string:
newch={"DRAGO":Character.new_dragon,"GOBLIN":Character.new_goblin}
And create instances just by calling
play[i]=newch[char]()
To handle errors, you can add just a single if statement checking whether the char string is in the list with dict keys.

How to complete this function then print it out, using Python?

I'm having a hard time to understand how to work with functions - I can make then but after that I don't know how to use them. My question is how can I print this code with a function?
string = "Hello"
reverse = string[::-1]
print(reverse)
I tried putting it in a function but I cannot make it print Hello.
def reverse_a_string(string):
string = "Hello"
reverse = string[::-1]
print(reverse)
also tried this
def reverse_a_string(string):
string = "Hello"
reverse = string[::-1]
print(reverse)
Nothing seems to work. I'm having same problem with this as well.
total = 0
def length(words):
for i in words:
total += 1
return total
Functions without a return value
Functions that just take action or do something without returning a value (for example, print).
Functions that don't return a value can be defined like that:
def sayHello():
print "Hello!"
And can be used (called) like that:
sayHello()
And the output will be:
Hello!
Function parameters
A function can also receive parameters (type of variables) from the caller. It's better to demonstrate it with an example.
A function that receives a name and greets this name:
def sayHelloTo(name):
print "Hello", name
It can be called like that:
sayHelloTo("Yotam")
And the output will be:
Hello Yotam
The parameters are the function's input.
Functions with a return value
Other functions, unlike sayHello() or sayHelloTo(name) (that just do something) can return a value. For example, let's make a function that rolls a dice (returns a random number between 1 and 6).
from random import randint
def rollDice():
result = randint(1, 6)
return result
The return keyword just sets the output value of the function and exits the function. An example use of the rollDice function will be:
dice = rollDice()
print "The dice says", dice
When the function hits a return keyword, it finishes and the return value (in our case, the variable result) will be placed instead of the function call. Let's assume randint(1, 6) has produced the number 3.
Result becomes 3.
Result is returned.
Now, instead of the line:
dice = rollDice()
We can treat the line as:
dice = 3
(rollDice() was replaced with 3)
Functions with parameters and a return value
Some functions (for example, math functions) can take inputs AND produce outputs. For example, let's make a function that receives 2 numbers and outputs the greater one.
def max(a,b):
if a > b:
return a
else:
return b
What it does is pretty clear, isn't it? If a is greater, it returns the value of it. Otherwise, returns the value of b.
It can be used like that:
print max(4, 6)
And the output will be:
6
Now, your case
What you want to do is a function that reverses a string. It should take 1 parameter (input) - the string you want to reverse, and output 1 value - the reversed string. This can be accomplished like that:
def reverse_a_string(my_text):
return my_text[::-1]
now you can do something like that:
s = raw_input("Please enter a string to be reversed\n") #input in Python3
r = reverse_a_string(s)
print r
r will contain the reversed value of s, and will be printed.
About your second function - well, I assume that based on this answer you can make it yourself, but comment me if you need assistance with the second one.
Local variables
About your 3rd example:
def reverse_a_string(string):
string = "Hello"
reverse = string[::-1]
print(reverse)
This is something that is really worth delaying and understanding.
the variable reverse is first used inside the function. This makes it a local variable.
This means that the variable is stored in the memory when the function is called, and when it finishes, it is removed. You can say it's lifetime is from when the function is called to when the function is done.
This means that even if you called reverse_a_string(string), you wouln't be able to use the reverse variable outside of the function, because it would be local.
If you do want to pass a value like that, you have to "declare" your variable outside of the function and to use the global keyword, like that:
reverse = "" #This makes reverse a global variable
def reverse_a_string(string):
global reverse #Stating that we are going to use the global variable reverse
reverse = string[::-1]
# Then you can call it like that:
reverse_a_string("Hello")
print reverse
The output will be
olleH
Although it's strongly not recommended to do it in Python, or in any other language.
Once you create a function you must call it. You have created the function reverse_a_string but then you never actually call it. Think about a function as a button that does something everytime it is pushed (or in our case called). If you never push the button then although it has the potential to do something, it never will. In order for the set of instructions to happen we need to push the button (or in our case call the function). So in order for your code to work you first need to define the function then actually call it:
def reverse_a_string():
string="Hello"
reverse = string[::-1]
print reverse
reverse_a_string()
Result: 'olleH'
If you want to pass your own string in to the function so it doesn't just return 'olleH' all the time your code needs to look like such:
def reverse_a_string(stringThatWillBeReversed):
reverse = stringThatWillBeReversed[::-1]
print reverse
reverse_a_string('whateverStringYouWant')
Result: The reverse of the string you entered.
Hope that helps!
I don't know whether you are asking how to define functions in python or something else
If you want to learn python functions, go to http://www.tutorialspoint.com/python/python_functions.htm or just write python tutorial in google, you will get billions of good sites
def reverse_a_string(string):
#function definition
reverse = string[::-1]
print(reverse)
#function call
reverse_a_string("your string")
But you to define function for this, you could simply do
print( string[::-1] )
# defines the 'Reverse a String' function and its arguments
def reverse_a_string():
print(string)
reverse = string[::-1]
print(reverse)
print("Type a string") # asks the user for a string input
string = input() # assigns whatever the user input to the string variable
reverse_a_string() # simply calls the function
for functions, you have to define the function, then simply call it with the function name i.e. funtion()
In my example, I ask for a string, assign that to the variable, and use it within the function. If you just want to print hello (I'm a little unclear from your question) then simply including the print("hello") or w/ variable print(string) will work inside the function as well.

why does Python lint want me to use different local variable name, than a global, for the same purpose

Given Python code such as
def func():
for i in range(10):
pass
for i in range(10):
pass
pylint complains
Redefining name 'i' from outer scope
What is the Pythonic way to write the above? Use a different variable locally, say j?
But why, when the variable means exactly the same in both cases (i for index). Let's say I change all local indexes to j and then later I find I want to use j as the second index in the glocal scope. Have to change again?
I can't disable lint warnings, I don't want to have them, I want to write Pythonic, and yet I want to use the same name for the same thing throughout, in the simple case like the above. Is this not possible?
You can avoid global variable conflict by not having any global variables:
def func():
for i in range(10):
pass
def _init_func():
for i in range(10):
pass
_init_func()
Any code that needs to run at module-init time can be put into a single function. This leaves, as the only executable code to run during module init: def statements, class statements, and one function call.
Similarly, if your code is not intended to be imported, but rather is a script to be run,
def func():
for i in range(10):
pass
def main():
for i in range(10):
pass
if __name__=="__main__":
main()
Because it eliminate the risk of being using one when you believe you are using the other. Lint tools are made to make your code more robust. By having all your variables having different names, you ensure that no such conflict could arise.
This is especially critical in interpreted language because the errors are not checked at "compile time". I once had the problem that the second call to a function gave me an error, because I renamed a function and I didn't realize that in some case There was a variable which was created with the same name as my function, and so, when I was trying to call my function, the interpreter tried to "call" my newly created variable, which never worked XD.
this lint policy will avoid that kind of problem.
Here is a sample code (this is a program to compute pi) :
from fractions import Fraction
def order(x):
r, old_r, n, old_n = 2, 1, 1, 0
while (x>=r):
r, old_r, n, old_n = r*r, r, 2*n, n
return order(x >> old_n) + old_n if old_n > 0 else 0
def term(m, n, i):
return Fraction(4 * m, n**(2*i+1) * (2*i+1))
def terms_generator(exp_prec):
ws = [ [term(parm[1], parm[2], 0), 0] + list(parm)
for parm in ((1, 44, 57),
(1, 7, 239),
(-1, 12, 682),
(1, 24, 12943))]
digits = 0
while digits<exp_prec:
curws = max(ws, key=lambda col: col[0])
digits = int(0.30103 *
(order(curws[0].denominator))
- order(curws[0].numerator))
yield curws[2] * curws[0], digits
curws[2] = -curws[2]
curws[1] += 1
curws[0] = term(curws[3], curws[4], curws[1])
expected_precision = 1000
pi = 0
for term, dgts in terms_generator(expected_precision):
pi += term
print("{} digits".format(dgts))
print("pi = 3.{}".format(int((pi-3)*10**expected_precision)))
In this case, I initialized a variable from a generator and the generator used another function which conflicted with my variable name once it was initialized by my generator. Well, It's not a very good example because here both names are global, but from it's structure, it wasn't immediately obvious that it would happen.
My point is that even if you KNOW how to program, you make mistakes and those practices will help reduce the risks for those to stay hidden.
The linter warns because i lives on after the loop, if it ran at least once. This means that if you were to use it without re-initializing it it would still have the value it had during the last iteration of the loop.
The way you use it is fine since i will always be reinitialized.
A useful practice could be to name all values in the outer scope in ALL_CAPS. This way no mistakes could be made.
This answer was rightfully determined to be wrong. Please see : https://stackoverflow.com/a/25072186

'module' object is not callable - calling method in another file

I have a fair background in java, trying to learn python. I'm running into a problem understanding how to access methods from other classes when they're in different files. I keep getting module object is not callable.
I made a simple function to find the largest and smallest integer in a list in one file, and want to access those functions in another class in another file.
Any help is appreciated, thanks.
class findTheRange():
def findLargest(self, _list):
candidate = _list[0]
for i in _list:
if i > candidate:
candidate = i
return candidate
def findSmallest(self, _list):
candidate = _list[0]
for i in _list:
if i < candidate:
candidate = i
return candidate
import random
import findTheRange
class Driver():
numberOne = random.randint(0, 100)
numberTwo = random.randint(0,100)
numberThree = random.randint(0,100)
numberFour = random.randint(0,100)
numberFive = random.randint(0,100)
randomList = [numberOne, numberTwo, numberThree, numberFour, numberFive]
operator = findTheRange()
largestInList = findTheRange.findLargest(operator, randomList)
smallestInList = findTheRange.findSmallest(operator, randomList)
print(largestInList, 'is the largest number in the list', smallestInList, 'is the smallest number in the list' )
The problem is in the import line. You are importing a module, not a class. Assuming your file is named other_file.py (unlike java, again, there is no such rule as "one class, one file"):
from other_file import findTheRange
if your file is named findTheRange too, following java's convenions, then you should write
from findTheRange import findTheRange
you can also import it just like you did with random:
import findTheRange
operator = findTheRange.findTheRange()
Some other comments:
a) #Daniel Roseman is right. You do not need classes here at all. Python encourages procedural programming (when it fits, of course)
b) You can build the list directly:
randomList = [random.randint(0, 100) for i in range(5)]
c) You can call methods in the same way you do in java:
largestInList = operator.findLargest(randomList)
smallestInList = operator.findSmallest(randomList)
d) You can use built in function, and the huge python library:
largestInList = max(randomList)
smallestInList = min(randomList)
e) If you still want to use a class, and you don't need self, you can use #staticmethod:
class findTheRange():
#staticmethod
def findLargest(_list):
#stuff...
from a directory_of_modules, you can import a specific_module.py
this specific_module.py, can contain a Class with some_methods() or just functions()
from a specific_module.py, you can instantiate a Class or call functions()
from this Class, you can execute some_method()
Example:
#!/usr/bin/python3
from directory_of_modules import specific_module
instance = specific_module.DbConnect("username","password")
instance.login()
Excerpts from PEP 8 - Style Guide for Python Code:
Modules should have short and all-lowercase names.
Notice: Underscores can be used in the module name if it improves readability.
A Python module is simply a source file(*.py), which can expose:
Class: names using the "CapWords" convention.
Function: names in lowercase, words separated by underscores.
Global Variables: the conventions are about the same as those for Functions.

How to retrieve a variable's name in python at runtime?

Is there a way to know, during run-time, a variable's name (from the code)?
Or do variable's names forgotten during compilation (byte-code or not)?
e.g.:
>>> vari = 15
>>> print vari.~~name~~()
'vari'
Note: I'm talking about plain data-type variables (int, str, list etc.)
Variable names don't get forgotten, you can access variables (and look which variables you have) by introspection, e.g.
>>> i = 1
>>> locals()["i"]
1
However, because there are no pointers in Python, there's no way to reference a variable without actually writing its name. So if you wanted to print a variable name and its value, you could go via locals() or a similar function. ([i] becomes [1] and there's no way to retrieve the information that the 1 actually came from i.)
Variable names persist in the compiled code (that's how e.g. the dir built-in can work), but the mapping that's there goes from name to value, not vice versa. So if there are several variables all worth, for example, 23, there's no way to tell them from each other base only on the value 23 .
Here is a function I use to print the value of variables, it works for local as well as globals:
import sys
def print_var(var_name):
calling_frame = sys._getframe().f_back
var_val = calling_frame.f_locals.get(var_name, calling_frame.f_globals.get(var_name, None))
print (var_name+':', str(var_val))
So the following code:
global_var = 123
def some_func():
local_var = 456
print_var("global_var")
print_var("local_var")
print_var("some_func")
some_func()
produces:
global_var: 123
local_var: 456
some_func: <function some_func at 0x10065b488>
here a basic (maybe weird) function that shows the name of its argument...
the idea is to analyze code and search for the calls to the function (added in the init method it could help to find the instance name, although with a more complex code analysis)
def display(var):
import inspect, re
callingframe = inspect.currentframe().f_back
cntext = "".join(inspect.getframeinfo(callingframe, 5)[3]) #gets 5 lines
m = re.search("display\s+\(\s+(\w+)\s+\)", cntext, re.MULTILINE)
print m.group(1), type(var), var
please note:
getting multiple lines from the calling code helps in case the call was split as in the below example:
display(
my_var
)
but will produce unexpected result on this:
display(first_var)
display(second_var)
If you don't have control on the format of your project you can still improve the code to detect and manage different situations...
Overall I guess a static code analysis could produce a more reliable result, but I'm too lazy to check it now
This will work for simple data types (str, int, float, list etc.)
def my_print(var_str) :
print var_str+':', globals()[var_str]
You can do it, it's just not pretty.
import inspect, sys
def addVarToDict(d, variable):
lineNumber = inspect.currentframe().f_back.f_lineno
with open(sys.argv[0]) as f:
lines = f.read().split("\n")
line = lines[lineNumber-1]
varName = line.split("addVarToDict")[1].split("(")[1].split(",")[1].split(")")[0].strip()
d[varName] = variable
d = {}
a=1
print d # {}
addVarToDict(d,a)
print d # {'a': 1}
I tried the following link from the post above with no success:
Googling returned this one.
http://pythonic.pocoo.org/2009/5/30/finding-objects-names
Just yesterday I saw a blog post with working code that does just this. Here's the link:
http://pyside.blogspot.com/2009/05/finding-objects-names.html
Nice easy solution using f-string formatting, which is native to Python 3.6 and later:
vari = 15
vari_name = f"{vari=}".split("=")[0]
print(vari_name)
Produces:
vari

Categories