Random number for variable when called - python-3.x

I'm fairly new in programming and python in general. I already learned for, if's, and while, and I'm trying to make a pretty decent rpg/dungeon game. I'm wondering how do I make a variable have a random number when used for the "damage".
I used randint(a, b) for the variable but it is only random once.
This is a creature example:
name_slime = "Red Slime"
slime_hp = randint(100, 200)
slime_atk = randint(1, 2)
slime_crit = 60
slime_evade = 10
slime_exp = randint(1, 5)
slime_chance = randint(50, 60)
And these will get called on another function:
def battle(enemy_name, enemy_hp, enemy_atk, enemy_crit, enemy_evade, enemy_exp):# Battle sequence
while enemy_hp > 0:
global player_hp, potion_count
print(f"{enemy_name}'s Stats:")
print(f"HP: {enemy_hp} Power: {enemy_atk} Crit Chance: {enemy_crit}% Evade: {enemy_evade}%\n")
print("Your Stats:")
....
print("Action:\n1. Attack\n2. Parry\n3. Use Potion")
choice = input("> ")
if choice == "1":
....
elif choice == "2":
....
elif choice == "3":
....
print(f"You gained {enemy_exp} EXP")
exp_check(enemy_exp)
print(f"Your EXP is now {player_exp}/{exp_limit}")
P.S: I scraped a lot of things in this code because it's quite long for there is a lot of lines for the calculation.
Here's the full code if anyone can help:
https://pastebin.com/iFMZyY4z
I'll just take the exp for this case.
In the variable "slime_exp" it should give a number between 1 and 5. But when i tried fighting the creature multiple times in one run (not exiting the terminal) it always give the same amount of exp each time.
I'm thinking that the randint(1, 5) is defined when the script is run and not when the variable is used.
This happens for all variable that have randint()
How can I make it so that it will be random when the variable is used?

Using the choice method is an alternative that might be suitable for you:
slime_exp = range(1,6) # slime_exp is now a variable of 'range' type!
For more infomation about the range() function see range in Python.
And whenever you use the variable slime_exp you can use choice(slime_exp).
choice is a function that returns a pseudo-random value from a list, range, tuple, string. For more information see choice in Python.
Note that, to use choice you have to "import" it first by doing one of these options:
from random import * (not very advised)
import random (in this case you should use random. choice instead of just choice)
or from random import choice
And when you want to use the variable slime_exp, you just use choice(slime_exp) instead of slime_exp. Note that this may be a good option if you don't need to use the same value several times since the exact value of choice(slime_exp) is "pseudo-randomized" everytime you use it.

You can write a function to update the slime_exp variable and call it when needed, like below.
slime_exp = randint(1, 5)
def update_slime_exp():
global slime_exp
slime_exp = randint(1, 5)
update_slime_exp()
print(slime_exp)
However, changing the state of global variable is not a good programming practise. Instead get the random number as return value and use it when needed instead of storing it in a global variable.

Related

how to use variable from function

def message(number):
`number+=2`
print(number)
ans = message(number)
return number`
if ans == 3:
`print("theory was right")`
number=1234
message(1)
print(number)
In the above code, I am not able to use variable returned from def() out of the function body. Is there a way I can do it? Pls. don't mind indents coz this is my first post here. thnx
I've tried
ans = number
also
ans = message()
but still not able to do get the output
Firstly, you build an infinite recursion - if you want to use a function inside itself, you have to insert a condition which will stop the recursion and let you get a result.
So, above ans = message(number), you should place if statement.
Secondly, you cannot use a variable out of a function, if it is not returned - it has never been counted.
You probably got confused it with possibilty of using global variables out of loops.
To sum up, if you want to check ans, you have to return it in a function and call the function like this (it is not the solution):
def function(x):
ans = message(number)
return ans
if funcion(x):
print("theory was right")

How to tackle the error str object is not callable

Whenever I am trying to run the given code it always gives the error 'str' object is not callable.
Somebody please tell me what is wrong with the code.
Here is the code:
def intel():
c=0
for i in num(1,9):
if((num[i]%2)==0):
c=c+1
return c
num = input()
out= intel()
print(out)```
Bachchu, welcome! There are a few different things going on here:
As usr2564301 explained, the TypeError: 'str' object is not callable is Traceback for statement for i in num(1,9): because the num() function does not exist unless you define one yourself. That is to say that functions like print() are built-in to Python such that you need not import additional modules to have automatic access to them. The num() function does not exist in the default 'namespace' which you have access to. Perhaps you did define one in another module and forgot to import it, or perhaps you did not mean to call that as a function, but it caused the error because unless you have visibility to it (for example through a def or import) then it does not exist as far as Python is concerned.
This segues into Carl Brubaker's assumption that you meant to use the range() function instead of num() altogether. The range() function would generate a list of [1,2,3,4,5,6,7,8] for your code to iterate through. It starts at the first argument (1) and goes up to but not including the second argument (9-1 = 8). I will add that perhaps, if you did indeed intend for the generation of a list, you probably meant to include 9 in the list, in which case you would need to use range(1,10).
As far as num() and input() are concerned, I don't think you are trying to define a num() function by entering it at the keyboard and assigning it to variable num via a call to the input() function.
The num = input() statement accepts user input from the keyboard and assigns it in string format to the variable num. As Carl Brubaker explained, you will need to convert (or cast if you are familiar with other languages) that data to int() before comparing it numerically. You can easily do this by wrapping the input() call:
num = int(input())
or like this:
num = input()
num = int(num)
One last piece of two-cents: The input() function can be passed a prompt string to present to the user so that when the control is passed to the terminal, the prompt will indicate to the user that it is expecting something. Here's an example:
num = int(input('Please enter a number: '))
As expected, this will present the user, at the terminal (command prompt), with the following:
Please enter a number:
Note that the blank space is a spacer so that the user's data will begin one space after the colon (for the sake of clarity).
At this juncture, we could guess what your objective is, but it would be best if you first cleaned up what we have pointed out here, then followup with outstanding issues, if any remain.

Is there a way changing actual value of an int without creating a new instance? [duplicate]

How can I pass an integer by reference in Python?
I want to modify the value of a variable that I am passing to the function. I have read that everything in Python is pass by value, but there has to be an easy trick. For example, in Java you could pass the reference types of Integer, Long, etc.
How can I pass an integer into a function by reference?
What are the best practices?
It doesn't quite work that way in Python. Python passes references to objects. Inside your function you have an object -- You're free to mutate that object (if possible). However, integers are immutable. One workaround is to pass the integer in a container which can be mutated:
def change(x):
x[0] = 3
x = [1]
change(x)
print x
This is ugly/clumsy at best, but you're not going to do any better in Python. The reason is because in Python, assignment (=) takes whatever object is the result of the right hand side and binds it to whatever is on the left hand side *(or passes it to the appropriate function).
Understanding this, we can see why there is no way to change the value of an immutable object inside a function -- you can't change any of its attributes because it's immutable, and you can't just assign the "variable" a new value because then you're actually creating a new object (which is distinct from the old one) and giving it the name that the old object had in the local namespace.
Usually the workaround is to simply return the object that you want:
def multiply_by_2(x):
return 2*x
x = 1
x = multiply_by_2(x)
*In the first example case above, 3 actually gets passed to x.__setitem__.
Most cases where you would need to pass by reference are where you need to return more than one value back to the caller. A "best practice" is to use multiple return values, which is much easier to do in Python than in languages like Java.
Here's a simple example:
def RectToPolar(x, y):
r = (x ** 2 + y ** 2) ** 0.5
theta = math.atan2(y, x)
return r, theta # return 2 things at once
r, theta = RectToPolar(3, 4) # assign 2 things at once
Not exactly passing a value directly, but using it as if it was passed.
x = 7
def my_method():
nonlocal x
x += 1
my_method()
print(x) # 8
Caveats:
nonlocal was introduced in python 3
If the enclosing scope is the global one, use global instead of nonlocal.
Maybe it's not pythonic way, but you can do this
import ctypes
def incr(a):
a += 1
x = ctypes.c_int(1) # create c-var
incr(ctypes.ctypes.byref(x)) # passing by ref
Really, the best practice is to step back and ask whether you really need to do this. Why do you want to modify the value of a variable that you're passing in to the function?
If you need to do it for a quick hack, the quickest way is to pass a list holding the integer, and stick a [0] around every use of it, as mgilson's answer demonstrates.
If you need to do it for something more significant, write a class that has an int as an attribute, so you can just set it. Of course this forces you to come up with a good name for the class, and for the attribute—if you can't think of anything, go back and read the sentence again a few times, and then use the list.
More generally, if you're trying to port some Java idiom directly to Python, you're doing it wrong. Even when there is something directly corresponding (as with static/#staticmethod), you still don't want to use it in most Python programs just because you'd use it in Java.
Maybe slightly more self-documenting than the list-of-length-1 trick is the old empty type trick:
def inc_i(v):
v.i += 1
x = type('', (), {})()
x.i = 7
inc_i(x)
print(x.i)
A numpy single-element array is mutable and yet for most purposes, it can be evaluated as if it was a numerical python variable. Therefore, it's a more convenient by-reference number container than a single-element list.
import numpy as np
def triple_var_by_ref(x):
x[0]=x[0]*3
a=np.array([2])
triple_var_by_ref(a)
print(a+1)
output:
7
The correct answer, is to use a class and put the value inside the class, this lets you pass by reference exactly as you desire.
class Thing:
def __init__(self,a):
self.a = a
def dosomething(ref)
ref.a += 1
t = Thing(3)
dosomething(t)
print("T is now",t.a)
In Python, every value is a reference (a pointer to an object), just like non-primitives in Java. Also, like Java, Python only has pass by value. So, semantically, they are pretty much the same.
Since you mention Java in your question, I would like to see how you achieve what you want in Java. If you can show it in Java, I can show you how to do it exactly equivalently in Python.
class PassByReference:
def Change(self, var):
self.a = var
print(self.a)
s=PassByReference()
s.Change(5)
class Obj:
def __init__(self,a):
self.value = a
def sum(self, a):
self.value += a
a = Obj(1)
b = a
a.sum(1)
print(a.value, b.value)// 2 2
In Python, everything is passed by value, but if you want to modify some state, you can change the value of an integer inside a list or object that's passed to a method.
integers are immutable in python and once they are created we cannot change their value by using assignment operator to a variable we are making it to point to some other address not the previous address.
In python a function can return multiple values we can make use of it:
def swap(a,b):
return b,a
a,b=22,55
a,b=swap(a,b)
print(a,b)
To change the reference a variable is pointing to we can wrap immutable data types(int, long, float, complex, str, bytes, truple, frozenset) inside of mutable data types (bytearray, list, set, dict).
#var is an instance of dictionary type
def change(var,key,new_value):
var[key]=new_value
var =dict()
var['a']=33
change(var,'a',2625)
print(var['a'])

Pythonic way of creating if statement for nested if statements

I'm kind of newbie as programmer, but I wish to master Python and I'm developing open source application. This application has function to gather some information. This function takes 1 parameter. This parameter can be 0, 1 or 2. 0 = False, 1 = True, 2 = Multi. Also I have an if statement that does 2 actions. 1st - (when False) gathers single type value, 2nd - (when True) gathers multiple type values and when parameter is 2 (multi) then it will gather single type (1st) and multiple types (2nd). My if statement looks like this:
if False:
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
elif True:
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
else:
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
Is there maybe better way of avoiding this kind of coding, like in last else statement when I call both single and multiple.
Thank you in advance.
One thing I learned from Python is that although it lacks the Switch operator, you can use dictionary in a similar fashion to get things done since everything is an object:
def get_single():
# define your single function
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
def get_multi():
# define your multi function
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
actions = {
0: [get_single],
1: [get_multi],
2: [get_single, get_multi]
}
parameter = 0 # replace this line with however you are capturing the parameter
for action in actions[parameter]:
action()
This way you avoid c+p your code everywhere and have it referenced from the function, and your "actions" dictionary define the function to be used based on the parameter given.
In this case since you have multiple functions you want to call, I kept all dictionary items as a list so the structure is consistent and it can be iterated through to perform any number of actions.
Ensure you use leave out the () in the dictionary so that the functions aren't instantiated when the dictionary is defined. And remember to add () when you are actually calling the function from the dictionary to instantiate it.
This is something you will often encounter and it is pretty much always bad practice to be repeating code. Anyway, the way to do this is use two if-statements. This way, even if the first case passes, the second case can still pass. Oh, and assuming your variable that can be 0, 1 or 2 is called x, then we could either use or and two checks:
if x == 0 or x == 2:
but, personally, I prefer using in on a tuple:
if x in (0, 2):
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
if x in (1, 2):
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)

Python: NameError: name "string" is not defined, not via input()

The function below checks to see if the first 9 digits of string (n) equate to the 10th character (an integer from 1-9 or X for 10).
def isISBN(n):
checkSum = 0
for i in range(9):
checkSum = checkSum + (eval(n[i])*(i+1))
if checkSum%11 == eval(n[9]) or (checkSum%11 == 10 and n[9] == 'X'): return True
else: return False
When I run the function for n='020103803X' I get an error:
NameError: name 'X' is not defined
I've searched for this problem and found that most people's issues were with input() or raw_input(), but as I am not using input(), I'm confused as to why I can't test if a character is a specific string. This is my first post as Python beginner, please tell if I'm breaking rules or what extra info I should include.
The problem is with your use of eval: eval('X') is the same as doing X (without the quotes). python sees that as a variable reference, and you have no variable named X.
There is no reason to use eval here. What are you hoping to accomplish? Perhaps you should be checking to see if the character is a digit?
if checkSum%11 == n[9].isdigit() or (checkSum%11 == 10 and n[9] == 'X'): return True
You're trying to get a response from
eval('X')
This is illegal, as you have no symbol 'X' defined.
If you switch the order of your if check, you can pass legal ISBNs. However, it still fails on invalid codes with an X at the end.
def isISBN(n):
checkSum = 0
for i in range(9):
checkSum = checkSum + (eval(n[i])*(i+1))
if (checkSum%11 == 10 and n[9] == 'X') or \
checkSum%11 == eval(n[9]):
return True
else:
return False
Note also that you can short-cut that return logic by simply returning the expression value:
return (checkSum%11 == 10 and n[9] == 'X') or \
checkSum%11 == eval(n[9])
Eval is not the proper usage, nor is the way you use it correct. For example, see Wikipedia which shows the use. You probably want to use a try: except: pair.
try:
int(n[i]
except:
print "this character is not a digit"
A call to eval is sometimes used by inexperienced programmers for all
sorts of things. In most cases, there are alternatives which are more
flexible and do not require the speed penalty of parsing code.
For instance, eval is sometimes used for a simple mail merge facility,
as in this PHP example:
$name = 'John Doe';
$greeting = 'Hello';
$template = '"$greeting,
$name! How can I help you today?"';
print eval("return $template;");
Although this works, it can cause some security problems (see §
Security risks), and will be much slower than other possible
solutions. A faster and more secure solution would be changing the
last line to echo $template; and removing the single quotes from the
previous line, or using printf.
eval is also sometimes used in applications needing to evaluate math
expressions, such as spreadsheets. This is much easier than writing an
expression parser, but finding or writing one would often be a wiser
choice. Besides the fixable security risks, using the language's
evaluation features would most likely be slower, and wouldn't be as
customizable.
Perhaps the best use of eval is in bootstrapping a new language (as
with Lisp), and in tutoring programs for languages[clarification
needed] which allow users to run their own programs in a controlled
environment.
For the purpose of expression evaluation, the major advantage of eval
over expression parsers is that, in most programming environments
where eval is supported, the expression may be arbitrarily complex,
and may include calls to functions written by the user that could not
have possibly been known in advance by the parser's creator. This
capability allows you to effectively augment the eval() engine with a
library of functions that you can enhance as needed, without having to
continually maintain an expression parser. If, however, you do not
need this ultimate level of flexibility, expression parsers are far
more efficient and lightweight.
Thanks everyone. I don't know how I didn't think of using int(). The reason I used eval() was because the past few programs I wrote required something like
x = eval(input("Input your equation: "))
Anyways the function works now.
def isISBN(n):
checkSum = 0
for i in range(9):
checkSum = checkSum + (int(n[i])*(i+1))
if n[9] == 'X':
if checkSum%11 == 10: return True
else: return False
elif checkSum%11 == int(n[9]): return True
else: return False

Resources