How to make a module called 'func' in python - python

I am trying to make a module but not sure what exactly they are. I will post what the requirements of it are.
REQUIREMENTS
Make a module called 'funct' that holds the following information -
def total(val) - returns sum of all # in the list 'val'.
def sub(val) - returns the difference of all # in the list 'val'.
def times(val) - returns the product of all # in the list 'val'.
def div(val) - returns the result of dividing all # in the list 'val'. If first # is 0, then the result is 0. If any other # are 0, use sys.exit to stop it & display 'invalid list.'
Here is what I'm thinking it is supposed to be like:
import funct
funct.total([1, 2, 3, 4])
funct.sub([1, 2, 3, 4])
funct.times([1, 2, 3, 4])
funct.div([1, 2, 3, 4])

A module in python is a file containing code, i.e. you need to create a file called funct.py in the same folder as your main.py (or whatever you called the example above).
Then you need to implement each of the required functions, i.e. you code should look like
def total(val):
pass
def sub(val):
pass
def times(val):
pass
def div(val):
pass
Then in place of pass you need to code up the required logic

A module is nothing else like a separate python file. So you can just create a file funct.py and define all the needed functions, so:
funct.py:
def total(lst : list) -> int:
acc = 0
for i in lst:
acc += i
return acc # return the accumulated sum
def sub(...):
pass
def times(...):
pass
def div(...):
pass
Then in another python file, but in the same folder, create the main.py file or any other filename which imports this module and uses the defined functions:
main.py
import funct
funct.total([1, 2, 3, 4])
funct.sub([1, 2, 3, 4])
funct.times([1, 2, 3, 4])
funct.div([1, 2, 3, 4])
Here you can see some further reading and informations about python modules.

Related

Python dynamic function parameters

When calling the function below, I can provide values that will be used instead of the default parameters in the function (see below).
cerebro.addstrategy(GoldenCross, fast=10, slow=25)
This works great for a small number of known parameters, but I am moving up to more complex systems. Essentially, I need to pass a fast_1, fast_2, fast_3, etc.... The total amount of these parameters will change (always around 100, but it can vary). Is there a statement that I can write that will dynamically add X amount of parameters to my function call?
I have tried using a for statement in the function call, but I received a syntax error.
I understood your question of two ways:
You want to call your function passing to it different parameters (that are optional), you can accomplish it like this:
def add(first, second=0, third=3):
return (first+second+third)
number_list = list(range(1, 200)) # Generates a list of numbers
result = [] # Here will be stored the results
for number in number_list:
# For every number inside number_list the function add will
# be called, sending the corresponding number from the list.
returned_result = add(1,second=number)
result.insert(int(len(result)), returned_result)
print(result) # Can check the result printing it
You want your function handles any number of optional parameters, as you don't know any way to determine how many they are, you can send a list or parameters, like this:
def add(first,*argv):
for number in argv:
first += number
return first
number_list = (list(range(1, 200))) # Generates a list of numbers
result = add(1,*number_list) # Store the result
print(result) # Can check the result printing it
Here you can find more information about *args
how about using *?
def addstrategy(GoldenCross, *fast, slow = 25): can be an example.
>>> def foo(a, *b, c = 36):
print(a, b, c)
>>> foo(1, 2, 3, 4, 5)
1 (2, 3, 4, 5) 36
You need to initialize fast in this case, however.
Two ways: Either use a variable number of arguments using * on the parameter or treat the parameter as an iterable.
def fun1(positional, optional="value", *args):
print(args) # args here is a tuple, since by default variable number of args using * will make that parameter a tuple.
def fun2(positional, args, optional="value"):
print(args) # args here will be dependant on the argument you passed.
fun1("some_value", "value", 1, 2, 3, 4, 5) # args = (1, 2, 3, 4, 5)
fun2("some_value", [1, 2, 3, 4, 5]) # args = [1, 2, 3, 4, 5]

no reference to Module.parameters() after using more than once

I have a class that inherits from torch.nn.Module,
now when I do this code:
d = net.parameters()
print(len(list(d)))
print(len(list(d)))
print(len(list(d)))
the output is:
10
0
0
So I have reference to the net.parameters() only once, whys that?
Then it apparently disappear..
I got this error while trying to make my own Optimizer, so I pass this net.parameters() as a parameter to my new class, and apparently I couldn't use it because of that odd situation.
This is working as expected. Module.parameters() returns an iterator, more specifically, a Python generator. One thing about them is that you cannot rewind a generator. So, in the first list(d) call, you are actually "consuming" all the generator. Then, if you try to do that again, it will be empty.
If you're wondering, the .parameters() implementation can be seen here, and it is very simple:
def parameters(self, recurse=True):
for name, param in self.named_parameters(recurse=recurse):
yield param
Perhaps it is easier to wrap your mind around it with this toy example:
def g():
for x in [0, 1, 2, 3, 4]:
yield x
d = g()
print(list(d)) # prints: [0, 1, 2, 3, 4]
print(list(d)) # prints: []

Understanding maxmin function

I am going through functions in Learning Python, this one is giving me a little trouble understanding, was wondering if anyone could help me understand it better, more specifically the if test(arg, res)
When I run the first function, it doesn't matter what I put as the first argument, then the second argument has to be a list, and it just spits the list back as written. I'm confused on when you combine the functions and print them together how it gives the max and min.
def minmax(test, *args):
res = args[0]
for arg in args[1:]:
if test(arg, res):
res = arg
return res
def lessthan(x, y): return x < y
def grtrthan(x, y): return x > y
print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))
You seem to be misunderstanding how the starred function argument works. When you call your function as minmax(something, [1, 2, ...]), args becomes a tuple of one element equal to [1, 2, ...]. Therefore the body of the loop never gets executed and the value of test does not matter. The function is supposed to be invoked as minmax(something, 1, 2, ...). This way args gets the value (1, 2, ...) and the loop goes through its elements.
Clarification: The answer is based on what you wrote. Your code snippet is correct and works exactly as intended.
I haven't read that book so I don't know the context, but it looks that function (minmax) is not well named. It does not return two values, it only returns one -- and which one depends on the testing function you give it. If you pass in the lessthan function:
print(minmax(lessthan, 4, 2, 1, 5, 6, 3))
you'll get 1, and if you pass in the grtrthan function:
print(minmax(grtrthan, 4, 2, 1, 5, 6, 3))
you'll get 6.

Best practice for setting the default value of a parameter that's supposed to be a list in Python?

I have a Python function that takes a list as a parameter. If I set the parameter's default value to an empty list like this:
def func(items=[]):
print items
Pylint would tell me "Dangerous default value [] as argument". So I was wondering what is the best practice here?
Use None as a default value:
def func(items=None):
if items is None:
items = []
print items
The problem with a mutable default argument is that it will be shared between all invocations of the function -- see the "important warning" in the relevant section of the Python tutorial.
I just encountered this for the first time, and my immediate thought is "well, I don't want to mutate the list anyway, so what I really want is to default to an immutable list so Python will give me an error if I accidentally mutate it." An immutable list is just a tuple. So:
def func(items=()):
print items
Sure, if you pass it to something that really does want a list (eg isinstance(items, list)), then this'll get you in trouble. But that's a code smell anyway.
For mutable object as a default parameter in function- and method-declarations the problem is, that the evaluation and creation takes place at exactly the same moment. The python-parser reads the function-head and evaluates it at the same moment.
Most beginers asume that a new object is created at every call, but that's not correct! ONE object (in your example a list) is created at the moment of DECLARATION and not on demand when you are calling the method.
For imutable objects that's not a problem, because even if all calls share the same object, it's imutable and therefore it's properties remain the same.
As a convention you use the None object for defaults to indicate the use of a default initialization, which now can take place in the function-body, which naturally is evaluated at call-time.
In addition and also to better understand what python is, here my little themed snippet:
from functools import wraps
def defaultFactories(func):
'wraps function to use factories instead of values for defaults in call'
defaults = func.func_defaults
#wraps(func)
def wrapped(*args,**kwargs):
func.func_defaults = tuple(default() for default in defaults)
return func(*args,**kwargs)
return wrapped
def f1(n,b = []):
b.append(n)
if n == 1: return b
else: return f1(n-1) + b
#defaultFactories
def f2(n,b = list):
b.append(n)
if n == 1: return b
else: return f2(n-1) + b
>>> f1(6)
[6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1, 6, 5, 4, 3, 2, 1]
>>> f2(6)
[1, 2, 3, 4, 5, 6]

Very weird Python variable scope behaviour

I'm having a problem with Python 2.7 that is driving me insane.
I'm passing an array to some functions and altough that variable is suposed to be local, in the end the value of the variable inside main is changed.
I'm a bit new to Python, but this goes against any common sense I got.
Any ideas of what I'm doing wrong?
def mutate(chromo):
# chooses random genes and mutates them randomly to 0 or 1
for gene in chromo:
for codon in gene:
for base in range(2):
codon[randint(0, len(codon)-1)] = randint(0, 1)
return chromo
def mate(chromo1, chromo2):
return mutate([choice(pair) for pair in zip(chromo1, chromo2)])
if __name__ == '__main__':
# top 3 is a multidimensional array with 3 levels (in here I put just 2 for simplicity)
top3 = [[1, 0], [0, 0], [1, 1]]
offspring = []
for item in top3:
offspring.append(mate(top3[0], item))
# after this, top3 is diferent from before the for cycle
UPDATE
Because Python passes by reference, I must make a real copy fo the arrays before using them, so the mate functions must be changed to:
import copy
def mate(chromo1, chromo2):
return mutate([choice(pair) for pair in zip(copy.deepcopy(chromo1), copy.deepcopy(chromo2))])
The problem you are having is stemming from the fact that arrays and dictionaries in python are passed by reference. This means that instead of a fresh copy being created by the def and used locally you are getting a pointer to your array in memory...
x = [1,2,3,4]
def mystery(someArray):
someArray.append(4)
print someArray
mystery(x)
[1, 2, 3, 4, 4]
print x
[1, 2, 3, 4, 4]
You manipulate chromo, which you pass by reference. Therefore the changes are destructive... the return is therefore kind of moot as well (codon is in gene and gene is in chromo). You'll need to make a (deep) copy of your chromos, I think.
try changing
offspring.append(mate(top3[0], item)) to
offspring.append(mate(top3[0][:], item[:]))
or use the list() function

Categories