How do I execute functions via sys.argv - python

I'm very new to coding (started 2 days ago) and for practice a friend gave me the task of writing a program that provides either the nth Fibonacci number or the sequence up to the nth point. I successfully completed that task using input() and directly asking the user for an n, now he extended the task and asked me to try getting the same results using sys.argv
After extensive use of google I figured out how to print all the given arguments and count them, but I cannot figure out any way of using those arguments in a function. Unfortunately I also can't seem to find the right keywords for google, leaving me a little stuck in no mans land.
Here's my most recent attempt:
import sys
from math import sqrt
print('Number of arguments:', len(sys.argv), 'arguments.')
print ('Argument List:', str(sys.argv))
Fibonacci = sys.argv[0]
value = sys.argv[1]
sequence = sys.argv[2]
def fib(value): int(1/sqrt(5)*(((1+sqrt(5))/2)**value-(((1-sqrt(5))/2)**value)))
print("The {}. value is".format(value), fib(value))
input("Close")
(Small detail, albeit unimportant: I translated the strings from German to English, which is also why it says "{}. value" rather than "{}st/nd/rd/th", the differentiation between those cases is a problem for a later date.)
Now I expect to be miles off target here, but using some of the expressions that worked for my input() based code is pretty much the last idea I have right now. Can anyone give me a pointer on how I can proceed here? Even a hint on what I should google would help, but as of now I'm completely out of ideas.
EDIT: I don't know if this is what you're supposed to do, but I've solved my problem and I thought I might as well post my code in case someone else stumbles upon this thread with a similar question. Here's my solution.
import sys
from math import sqrt
Fibonacci = sys.argv[0]
Entscheidung = (sys.argv[1])
n = int(sys.argv[2])
sequence = []
if Entscheidung == "Stelle":
def fib(n): return int(1/sqrt(5)*(((1+sqrt(5))/2)**n-((1-sqrt(5))/2)**n))
print("Die {}. Stelle beträgt:{}".format(n, fib(n)))
elif Entscheidung == "Folge":
def fib(n): return int(1/sqrt(5)*(((1+sqrt(5))/2)**n-((1-sqrt(5))/2)**n))
for i in range(n):
sequence.append(fib(i + 1))
print('[%s]' % ', '.join(map(str, sequence)))
input("Schließen")
Note that I'm still an absolute beginner and this solution might be inefficient, badly written, confusingly formatted, I wouldn't know. All I can guarantee is that it does the job.

Yup, n = int(sys.argv[2]) was the charm.
Now that you're an expert at cracking sys.argv, you might want to $ pip install click and let that package do some of the parsing for you: https://click.palletsprojects.com/en/7.x/
Conditionally executing def is an option, I suppose, but a bit odd.
Pasting the same definition into both if branches is not helpful.
Just def it once, up top.

Here's a refactoring of your code with the following changes:
Don't define the same function twice. Instead, define two separate functions, and decide which one to call depending on the desired semantics.
Don't capitalize variables. Capitalized names are conventionally reserved for class names in Python.
Remove the final input. Surely your friend wanted you to make a program which can be properly reused; requiring user interaction ruins that.
Don't use sys.argv[0] for anything. If it's not used, there's no need to capture it (and if you should need it later, it's still there).
Wrap the entry point in if __name__... so that this piece of code can be imported into another program without side effects.
from math import sqrt
def fib_nth(n):
return int(1/sqrt(5)*(((1+sqrt(5))/2)**n-((1-sqrt(5))/2)**n))
def fib_seq(n):
sequence = []
for i in range(n):
sequence.append(fib_nth(i + 1))
return sequence
if __name__ == '__main__':
import sys
entscheidung = sys.argv[1]
n = int(sys.argv[2])
if entscheidung == "Stelle":
print("Die {}. Stelle beträgt:{}".format(n, fib_nth(n)))
elif entscheidung == "Folge":
print('[%s]' % ', '.join(map(str, fib_seq(n))))

Related

typeerror print_slow() takes 1 positional argument but 2 were given

so im fiddling around in pytbon cuz im bored and i realise i try to slow print a input i have earlier in the code i bave defined slow print ive imported every thing i need but when i run it it saw its got 1 positional argument buts been give 2 and im not that good at coding and am only a young student so coupd anyone be a huge help and explain it in basic terms
`
import sys
import os
import time
def print_slow(str):
for letter in str:
sys.stdout.write(letter)
sys.stdout.flush()
time.sleep(0.1)
num1 = int(input("Chose any number: "))
print_slow("Did you say",num1)
so my issue is that i cant seem to get it to slow print i expected this to work like it always does but i've never slow printed an input before
Replace print_slow("Did you say", num1) by print_slow(f"Did you say {num1}") and you should be good to go. This is (in my opinion) a slightly simpler solution than Cobra's. Here we are using Formatted strings(example) which you will encounter often going forward and that you should take a couple of minutes to understand.
Also, as mentioned in the comments of your post, DO NOT NAME A VARIABLE str (or more generally, do not name a variable with a type name) for it will mess things up later.
You are implicitly checking that the input value is of type int by converting the input string. If you insist on doing that then you might find this easier:
from time import sleep
def print_slow(*args):
for arg in args:
for c in str(arg):
print(c, flush=True, end='')
sleep(0.1)
print()
v = int(input('Choose any number: '))
print_slow('Did you say ', v, '?')

I am trying to run a random variable multiple times

I am very new to python, and am running into an issue I don't fully understand. I am trying to get a random variable to run multiple times, but for some reason it just returns the same random value x times.
I am not entirely certain what to try aside from the code I have already done.
lowTreasureList = "50 gold", "Healing Potion", "10x Magic Arrows", "+1 Magic Weapon"
def ranLowLoot(lowLootGiven):
# This function returns a random string from the passed list of strings.
lootIndex = random.randint(0, len(lowLootGiven) - 1)
return lowLootGiven[lootIndex]
lowLoot = ranLowLoot(lowTreasureList)
treasureSelection = int(input())
if treasureSelection == 1:
numLowTreasure = int(input('How many treasures? '))
for i in range(numLowTreasure):
ranLowLoot(lowTreasureList)
print(lowLoot)
When I do this I get the same random treasure (numLowTreasure) times, but I am trying to get it to select a new random treasure each time.
If you haven't already, it will help to read the documentation on the random module.
There are three alternatives to random.randint that are more suited to your purpose:
random.randrange(start, stop, [step]): step is optional and defaults to one. This will save you the len(...) - 1 you are using to get lootIndex, since stop is an exclusive bound.
random.randrange(stop): uses a default start of zero and default step of 1, which will save you passing 0 as your start index.
random.choice(seq): you can pass your function's parameter lowLootGiven to this as seq, which will save you from using indices and writing your own function entirely.
As for why you're getting the repeated treasure, that's because you aren't updating your variable lowLoot in your for loop. You should write:
for i in range(numLowTreasure):
lowLoot = ranLowLoot(lowTreasureList)
print(lowLoot)
Last thing I want to say is that python is nice for writing simple things quickly. Even if there was some bigger context that you were writing this code in, I might have written it like this:
lowTreasureList = ("50 gold", "Healing Potion", "10x Magic Arrows", "+1 Magic Weapon")
if int(input()) == 1:
for i in range(int(input('How many treasures? '))):
print(random.choice(lowTreasureList))
Using the round parentheses around the tuple declaration like I did isn't necessary in this case, but I like to use it because if you want to make the tuple declaration span multiple lines, it won't work without them.
Reading documentation on standard libraries is something I almost always find helpful. I think Python's documentation is great, and if it's bit too much to digest early on, I found tutorialspoint to be a good place to start.
The problem is that in the main loop you are discarding the result of the call to ranLowLoot(). As a minimal fix, in the main loop assign the result of that function call. Use:
lowLoot = ranLowLoot(lowTreasureList)
rather than simply:
ranLowLoot(lowTreasureList)
As a better fix, ditch your function completely and just use random.choice() (which does what you are trying to do, with much less fuss):
import random
lowTreasureList = ["50 gold", "Healing Potion", "10x Magic Arrows", "+1 Magic Weapon"]
treasureSelection = int(input())
if treasureSelection == 1:
numLowTreasure = int(input('How many treasures? '))
for i in range(numLowTreasure):
lowLoot = random.choice(lowTreasureList)
print(lowLoot)

Repeating a function with another function

for an assignment we needed to make a function that flipped a coin and another to flip it 100 times. I was able to make a function that flipped a coin, but got stuck when trying to call it a 100 times with another function. This is what I have right now:
import random
def TC():
face = random.randint(0,1)
if face == 1:
return "head"
else:
return "tail"
print TC()
def ply(flips):
for i in range(flips):
return TC()
print ply(100)
When I run it it just says 'none.' Please tell me where I am going wrong. Thank You!
Just to start, your method naming is very bad. I doubt this is how your professor is teaching you to name methods and variables. It's ugly, against Python standards and hard to read I suggest you take some time and read PEP 8 it's how python was intended to be written.
So instead of TC you should use something like flip_coin and instead of ply use something like play_coin_flip or even simply play.
Next I don't know if I'm stepping outside of what you have learned but instead of using randon.randint you can use randon.choice.
And finally, as others have said, when you return you quit any other execution in a function and return whatever variable you retrun in that statement thus nullifying any other iterations of the loop you're performing. I suggest something like the below as a better program with corrections applied to make it function as intended.
from random import choice
faces = ['head', 'tail']
def flip_coin():
face = choice(faces)
return face
def play_coin_flip(flips = 1):
for i in range(flips):
print(flip_coin)
if __name__ == "__main__":
play_coin_flip(100)

Change python command to subtract value instead of add in MYSQL

Just got one other question for my python plugin.
Here is the code:
def cmd_give(self, data, client=None, cmd=None):
"""
^3<player> <money> - Give someone however much money you want.
"""
input = self._adminPlugin.parseUserCmd(data)
if not data:
client.message('^7 correct syntax is !give <player> <money>')
return False
else:
if len([x for x in data if x.isspace()]) < 1:
client.message('^7 correct syntax is !give <player> <money>')
return False
else:
input_data = data.split(' ',1)
scname = input_data[0]
ammount = int(input_data[1])
sclient = self._adminPlugin.findClientPrompt(scname, client)
if not sclient: return False
self.earn_money(sclient, ammount)
return True
Now this obviously adds the value given in the command to the user inputting into mysql.
I'm also wanting a command to subtract any value given in the command as well.
So this command above is a give and I also want a take.
My problem is I don't know what the change is to minus the amount off the value input instead of adding.
Hope someone can help,
Thanks guys.
Without modifying the function that does the actual addition, the suggestion by Rob Watts in a comment will work:
ammount = -int(input_data[1])
You can either create a new function, cmd_take, and do that there, or have a more general function (cmd_transaction?) that takes an extra argument (eg give) and has the appropriate logic:
if not give:
ammount = -int(input_data[1])
In the first case, it would be good practice to extract most of the code to a helper function, to avoid repetition, but if you don't know python and this is just a one time thing, having a cmd_take function that is exactly like command_give, except for that one line, is the simplest solution.

How to split python script in parts and to import the parts in a loop?

First, sorry for my stupid title :) And here is my problem.. Actually it's not a problem. Everything works, but I want to have better structure...
I have a python script with a loop "looped" each second.
In the loop there are many many IFs. Is it possible to put each IF in a separate file and then to include it in the loop? So this way every time the loop is "looped", all the IFs will be passed, too..
There are too many conditions in my script and all of them are different generally from the otheres so I want to have some kind of folder with modules - mod_wheather.py, mod_sport.py, mod_horoscope.py, etc..
Thanks in advance. I hope I wrote everything understandable..
EDIT:
Here is a structural example of what I have now:
while True:
if condition=='news':
#do something
if condition=='sport':
#so something else
time.sleep(1)
It will be good if I can have something like this:
while True:
import mod_news
import mod_sport
time.sleep(1)
And these IFs from the first example to be separated in files mod_news.py, mod_sport.py...
perhaps you wonder how to work with your own modules in general.
make one file named 'weather.py' and have it contain the appropriate if-statements like:
""" weather.py - conditions to check """
def check_all(*args, **kwargs):
""" check all conditions """
if check_temperature(kwargs['temperature']):
... your code ...
def check_temperature(temp):
-- perhaps some code including temp or whatever ...
return temp > 40
same for sport.py, horoscope.py etc
then your main script would look like:
import time, weather, sport, horoscope
kwargs = {'temperature':30}
condition = 'weather'
while True:
if condition == 'weather':
weather.check_all(**kwargs)
elif condition == 'sport':
sport.check_all()
elif condition == 'horoscope':
horoscope.check_all()
time.sleep(1)
edit: edited according to the edit in your question. Note that I suggest importing all modules only one time, at the beginning of the script, and using its functions. This is better than executing code by importing. But if you insist, you could use reload(weather), which actually performs a reload including code execution. But I cannot stress too much that using functions of external modules is a better way to go!
Put them in functions in separate files and then Import them:
"""thing1.py
A function to demonstrate
"""
def do_things(some_var):
print("Doing things with %s" % (some_var))
``
"""thing2.py
Demonstrates the same thing with a condition
"""
def do_things(some_var):
if len(some_var) < 10:
print("%s is < 10 characters long" % (some_var))
else:
print("too long")
``
"""main_program.py"""
import thing1, thing2
myvar = "cats"
thing1.do_things(myvar)
thing2.do_things(myvar)
I believe you are looking for some kind of PHP-like include() or C prepocessor #include. You would have a file such as the included.py below:
a = 2
print "ok"
and another file which has the following code:
for i in values:
import included
and you want the result to be equivalent to
for i in values:
a = 2
print "ok"
Is it what you are looking for? If so... no, it is not possible. Once Python imports a module, the code of the module is executed and following imports of the same mode only retrieve the already imported instance of the module. The code of a module is not executed everytime it is imported.
I can invent some crazy ways of doing it (let us say, file.read() + eval(), or calling reload() in an imported module.) but it would be a bad idea anyway. I bet we can think of a better solution to your real problem :)
Perhaps all you need is to call functions in your loop; and have those functions in other modules, which you import as needed.
while true:
if condition:
from module_a import f
f()
if condition2
from module_b import g
g()
Though the above is legal Python, and so answers your question, you should in practice write all the imports at the top of your file.
You could import the needed modules if they're needed, for example:
if condition:
import weather
... do something
However I'm not sure if that's what you really want.
I have a python script with a loop "looped" each second. In the loop
there are many many IFs.
Then you must optimize the repeatedly executed tests. Suppose there are 50 IFs blocks in your code and that in a turn of the for-loop, the N th condition is True: that means that the N-1 other conditions must be tested before the N th is tested and triggers the execution of the corresponding code.
It would be preferable to do so:
# to_include.py
def func_weather(*args,**kwargs):
# code
return "I'm the weather"
def func_horoscope(*args,**kwargs):
# code
return "Give me your birth'date"
def func_gastronomy(*args,**kwargs):
# code
return 'Miam crunch'
def func_sports(*args,**kwargs):
# code
return 'golf, swimming and canoeing in the resort station'
didi = {'weather':func_weather, 'horoscope':func_horoscope,
'gastronomy':func_gastronomy, 'sports':func_sports}
and the main module:
# use_to_include.py
import to_include
x = 'sports'
y = to_include.didi[x]()
# instead of
# if x =='weather' : y = func_weather()
# elif x=='horoscope' : y = func_horoscope()
# elif x=='gastronomy': y = func_gastronomy()
# elif x=='sports' : y = func_sports()
print y
result
golf, swimming and canoeing in the resort station

Categories

Resources