Declaring a variable of unknown type in Python?

I have a situation in Python (cough, homework) where I need to multiply EACH ELEMENT into a given list of objects a certain number of times and return the output of the items. The problem is that the given sample data is of different types. For example, one case might introduce a list of strings whose elements I need to multiply, while others might be int. So my return type must change. I would like to do this without checking what each object type is. Is there a way to do this? I know that in C # I could just use "var", but I don't know if such a thing exists in Python?

I understand that variables do not have to be declared, but in this case, I don't see any way to get around this. Here's the function I made:

def multiplyItemsByFour(argsList):

output = ????

for arg in argsList:
        output += arg * 4

return output

      

See how I need to add to the output variable. If I just try to strip the output assignment on the first line, I get an error that the variable was not defined. But if I assign 0 or "to it for an empty string, an exception may be thrown as you cannot add 3 to the string or" a "to an integer, etc.

Here are some examples of inputs and outputs:

Input:  ('a','b')  Output:  'aaaabbbb'
Input:  (2,3,4)    Output:  36

      

Thank!

+2


source to share


11 replies


Very simple in Python. You need to get the data type in your list - use the type () function on the first element - type (argsList [0]). Then, to initialize the output (where do you have ???? now), you need a null or zero value for that type. So, just like int () or float () or str () returns zero or zero for its type so that it type (argsList [0]) () returns null or null for whatever type you have in your list.

So here's your function with one minor modification:



def multiplyItemsByFour(argsList):
    output = type(argsList[0])()
    for arg in argsList:
        output += arg * 4
    return output

      

Works with :: argsList = [1, 2, 3, 4]

or [1.0, 2.0, 3.0, 4.0]

or "abcdef"

... etc,

+2


source


def fivetimes(anylist):
  return anylist * 5

      

As you can see, if you are given a list argument, there is no need for any assignment to "multiply it by the given number of times and return the result". You are talking about this list; how is this given to you if not (the most natural way) as an argument to your function? Not that it matters a lot - if it's a global variable, a property of an object, what's your argument, etc., it still doesn't require any assignment.

If you were not allowed to enforce a "home" ban on the list operator *

and just needed to implement it yourself, this would require an assignment, but not a declaration:

def multiply_the_hard_way(inputlist, multiplier):
    outputlist = []
    for i in range(multiplier):
        outputlist.extend(inputlist)
    return outputlist

      

You can simply create an empty "magicaly" list: there is no need to "declare" it as anything, it is an empty list, and the Python compiler knows it as well as you or any reader of your code. Binding to a name outputlist

doesn't require any special ritual from you, just binding (aka assign) itself: names have no types, only objects have types ... what Python! -)

Edit : The OP is now saying that the output should not be a list, but rather int, float, or maybe a string, and is not given an indication of what. I asked for clarification - multiplying a list ALWAYS returns a list, so he must understand something different from what he originally said that he should have multiplied the list. Meanwhile, here's another attempt at mind reading. Perhaps it should return a list in which EACH ITEM from the input list is multiplied by the same factor (regardless of whether this element is int, float, string, list, ...). Then:

define multiply_each_item(somelist, multiplier):
  return [item * multiplier for item in somelist]

      

Look ma, no hands ^ H ^ H ^ H ^ H ^ H destination. (This is known as "list comprehension" by the way).

Or maybe (unlikely, but my mind reading hat may be suffering from tampering with my tin foil hat, you will need to go to the crazy joker's store for them to customize them) he should (say) multiply each list item as if they would be the same type as the first element, but return them as their original type, so for example

>>> mystic(['zap', 1, 23, 'goo'], 2)
['zapzap', 11, 2323, 'googoo']
>>> mystic([23, '12', 15, 2.5], 2)
[46, '24', 30, 4.0]

      

Even this very mystical spec MAY be posted ...:



>>> def mystic(alist, mul):
...   multyp = type(alist[0])
...   return [type(x)(mul*multyp(x)) for x in alist]
... 

      

... although I highly doubt the spec is really coded in the mysterious runes of this homework. Almost any particular specification can be implemented or proven, probably not possible as stated (requiring you to solve the halting problem, or requiring that P == NP, say ;-). It might take some work (like "proving color theorem 4", -) ... but still less than it takes to magically explain what the actual IS specification is, from a collection of mutually contradictory observations, no examples, etc. etc. Although in our day-to-day work as a software developer (ah, for the good old days when we had to deal with, there was homework!), We certainly encounter many such cases (and have to solve them,to earn our daily bread;).

EditEdit: Finally after seeing the exact spec, I point out that I have already implemented this, anyway, here it appears again:

def multiplyItemsByFour(argsList):
  return [item * 4 for item in argsList]

      

EditEditEdit: Finally / finally see a more precise spec with examples (deluxe! -):

Input: ('a','b') Output: 'aaaabbbb' Input: (2,3,4) Output: 36

      

So why was it summing (and you can't use sum

, since it won't work on strings) of the items in the input list, each multiplied by four. My preferred solution:

def theFinalAndTrulyRealProblemAsPosed(argsList):
  items = iter(argsList)
  output = next(items, []) * 4
  for item in items:
    output += item * 4
  return output

      

If you are prohibited from using some of these constructs, like built-in items

and iter

, there are many other possibilities (slightly worse), for example:

def theFinalAndTrulyRealProblemAsPosed(argsList):
  if not argsList: return None
  output = argsList[0] * 4
  for item in argsList[1:]:
    output += item * 4
  return output

      

For empty, the argsList

first version returns []

, the second returns None

- not sure what you should do in this case anyway.

+6


source


My guess is that the purpose of your homework is to duck you. The basic idea is that you don't worry too much about types, you just worry about whether the behavior is working properly. A classic example:

def add_two(a, b):
    return a + b

print add_two(1, 2)  # prints 3

print add_two("foo", "bar")  # prints "foobar"

print add_two([0, 1, 2], [3, 4, 5])  # prints [0, 1, 2, 3, 4, 5]

      

Note that when you def

execute a function in Python, you are not declaring the return type anywhere. It is quite obvious that the same function returns different types based on its arguments. He considered dignity, even; think that in Python we only need one definition add_two()

and we can add integers, add floats, concatenate strings and concatenate lists with it. Statically typed languages ​​would require multiple implementations if they had no escape code, for example variant

, but Python is dynamically typed. (Python is strongly typed but dynamically typed. Some will say that Python is weakly typed, but it is not. In a weakly typed language like JavaScript, an expression 1 + "1"

will give you the result 2; in Python, this expression just throws an exceptionTypeError

.)

It is considered very bad style to try and validate the arguments to figure out their types and then do things based on the types. If you need to make your code reliable, you can always use a block try

:

def safe_add_two(a, b):
    try:
        return a + b
    except TypeError:
        return None

      

See also the Wikipedia page on print duck .

+2


source


Are you sure this is for Python beginners? For me, the cleanest way to do this is with reduce () and lambda, both of which are not typical beginner tools, and sometimes discouraging even experienced Python programmers:

def multiplyItemsByFour(argsList):
    if not argsList:
        return None
    newItems = [item * 4 for item in argsList]
    return reduce(lambda x, y: x + y, newItems)

      

Like Alex Martelli, I quickly checked the empty list at the beginning, which returns None. Please note, if you are using Python 3, you must import functools to use reduce ().

Basically, the reduce (lambda ...) solution is very similar to other suggestions for setting up an accumulator using the first input element and then processing the rest of the input; but just more concise.

+2


source


You don't need to declare variable types in python; a variable has a type regardless of what is assigned to it.

EDIT:

To fix the re-expression issue, try the following:

def multiplyItemsByFour(argsList):

output = argsList.pop(0) * 4

for arg in argsList:
        output += arg * 4

return output

      

(This is probably not the most pythonic way to do it, but it should at least start with your output variable as the correct type, assuming the entire list is of the same type)

+1


source


Python is dynamically typed, you don't need to declare the type of a variable, because a variable has no type, only values ​​matter. (Any variable can store any value; a value never changes its type during its existence.)

def do_something(x):
    return x * 5

      

This will work for whatever x

you pass it to, the actual result depending on what type the value is in x

. If it x

contains a number, it just does a regular multiplication, if it contains a string, the string will repeat five times in a row, for lists, etc. She will repeat the list five times, and so on. For custom types (classes), it depends on whether the class has an operation defined for the multiplication operator.

+1


source


You have provided these ins and outs:

Input: ('a', 'b') Output: 'aaaabbbb' Input: (2,3,4) Output: 36

I don't want to write a solution to your homework for you, but I want to point you in the right direction. But I'm still not sure I understand what the problem is, because the problem I understand seems a bit tricky to introduce to a Python class.

The easiest way to solve this requires the arguments to be passed in a list. Then you can look at the first item in the list and work with it. Here is a function that requires the caller to pass a list of two elements:

def handle_list_of_len_2(lst):
   return lst[0] * 4 + lst[1] * 4

      

Now, how can we do this across two elements? Well, in your example code, you weren't sure what to assign to your output to a variable. How about assigning lst [0]? Then it always has the correct type. Then you can iterate over all other items in lst and accumulate in your output variable using + = as you wrote. If you don't know how to loop over a list of items but miss the first thing on the list, do a Google search for "python snippet list".

Now, how can we make this not require the user to collect everything into a list, but just call a function? What we really want is some way to take whatever arguments the user wants to pass to the function and make a list of them. There may be special syntax for declaring a function where you tell Python that you just want the arguments to be included in the list. You can check out a good tutorial and see what it says on how to define a function.

Now that we've covered (in general) how to accumulate a response using + =, let's look at other ways to accumulate a response. If you know how to use a list comprehension, you can use one of these to return a new list based on the list of arguments, with the multiplication being performed on each argument; you could somehow narrow the list down to one element and return it. Python 2.3 and newer have a built-in feature called sum()

and you can read about it. [EDIT: Oh drat, sum()

only works on numbers. See the note added at the end.]

Hope this helps. If you are still very confused, I suggest you contact your teacher and ask for clarification. Good luck.

PS Python 2.x has a built-in feature called reduce()

and can be implemented sum()

with reduce()

. However, the creator of Python thinks it's better to use sum()

, and in fact he removed it reduce()

from Python 3.0 (well, he moved it into a module called functools

).

PPS If you find that working on the list is working, here's one more thing to think about. If you use a list comprehension and then pass the result in sum()

, you are creating a list that will be used once and then discarded. Wouldn't it be neat if we could get the result, but instead of creating the entire list and then discarding it, we could just use the function sum()

on the list items as quickly as they are generated? You can read the following: Generator Expressions and List Comprehension

EDIT: Oh drat, I assumed the built-in Python sum()

would use duck typing. In fact, it's only documented to work with numbers. I am disappointed! I will need to search and see if there has been any discussion about this and see why they did it the way they did it; they probably had good reasons. Meanwhile, you can also use your + = solution. Excuse me.

EDIT: Ok, after reading the other answers, I now notice two ways suggested to remove the first item in the list.

For simplicity's sake, because you look like a Python beginner, I suggested simply using output = lst[0]

and then using list slicing to skip the previous item in the list. However, Wooble suggested using in his answer output = lst.pop(0)

, which is a very clean solution: it gets the null thing in the list, and then you can just loop over the list and automatically skip the null thing. However, this "mutates" the list! It is better if a function like this has no "side effects" like changing the list passed to it. (If the list is not a special list created just for this function call, for example in list*args

.) Another way is to use the "list slice" trick to make a copy of the list in which the first item was removed. Alex Martelli provided an example of how to make an "iterator" using a Python function called iter()

and then using an iterator to get the "next" thing. Since the iterator hasn't been used yet, the next thing is the null thing in the list. This isn't really a beginner, but it's the most elegant way to do it in Python; you can pass a really huge list to a function and Alex Martelli's solution won't mutate the list or waste memory by making a copy of the list.

+1


source


No need to test objects, just multiply them!

'this is a string' * 6
14 * 6
[1,2,3] * 6

      

everything just work

0


source


Try the following:

def timesfourlist(list):
 nextstep = map(times_four, list)
 sum(nextstep)

      

map executes the function passed in each element of the list (returns a new list) and then sums + = in the list.

0


source


If you just want to fill a gap in your code, you can try setting object=arglist[0].__class__()

to give it the null equivalent value of that class.

>>> def multiplyItemsByFour(argsList):
    output = argsList[0].__class__()
    for arg in argsList:
            output += arg * 4
    return output

>>> multiplyItemsByFour('ab')
'aaaabbbb'
>>> multiplyItemsByFour((2,3,4))
36
>>> multiplyItemsByFour((2.0,3.3))
21.199999999999999

      

This will fail if the list is empty, but you can check this case at the beginning of the function and return whatever you think you want.

0


source


Thanks to Alex Martelli, you have the best possible solution:

def theFinalAndTrulyRealProblemAsPosed(argsList):
    items = iter(argsList)
    output = next(items, []) * 4
    for item in items:
        output += item * 4
    return output

      

It is beautiful and elegant. First we create an iterator with iter()

, then we use next()

to get the first object in the list. We then accumulate as we iterate through the rest of the list and we're done. We never need to know the type of objects in argsList, and indeed they can be of different types if all types can have an operator +

applied to them. It's a duck.

I got confused a while ago and thought you wanted a function that, instead of taking an explicit list, just took one or more arguments.

def four_x_args(*args):
    return theFinalAndTrulyRealProblemAsPosed(args)

      

The *args

function argument tells Python to collect all the arguments to that function and make a tuple of them; then the tuple is associated with the name args

. You can easily compose a list from it and then you can use a method .pop(0)

to get the first item from the list. It costs memory and time to create the list, which is why the solution is iter()

so elegant.

def four_x_args(*args):
    argsList = list(args)  # convert from tuple to list
    output = argsList.pop(0) * 4
    for arg in argsList:
        output += arg * 4
    return output

      

This is just Wooble's solution rewritten to use * args.

Examples of calling it:

print four_x_args(1)  # prints 4
print four_x_args(1, 2)  # prints 12
print four_x_args('a')  # prints 'aaaa'
print four_x_args('ab', 'c') # prints 'ababababcccc'

      

Finally, I will be angry and complain about the decision you made. This solution depends on the base class of the object having a sensible zero or zero, but not all classes have this. int()

returns 0

and str()

returns ''

(empty string), so they work. But how about this:

class NaturalNumber(int):
    """
    Exactly like an int, but only values >= 1 are possible.
    """
    def __new__(cls, initial_value=1):        
        try:
            n = int(initial_value)
            if n < 1:
                raise ValueError
        except ValueError:
            raise ValueError, "NaturalNumber() initial value must be an int() >= 1"
        return super(NaturalNumber, cls).__new__ (cls, n)


argList = [NaturalNumber(n) for n in xrange(1, 4)]

print theFinalAndTrulyRealProblemAsPosed(argList)  # prints correct answer: 24

print NaturalNumber()  # prints 1
print type(argList[0])()  # prints 1, same as previous line

print multiplyItemsByFour(argList)  # prints 25!

      

Good luck with your studies, and I hope you enjoy Python as much as I do.

0


source







All Articles