I am trying to write a function, that applies a function to a list. I am trying to capitalise all the words in a list but can't get it to work. Here is what I've done so far:
list = ("hello", "this", "is", "a", "test")
def firstFunction(x):
return list.upper()
print firstFunction
The error I get is:
<function firstFunction at 0x0000000002352A58>
I'm really stuck on what to do next, any help would be greatly appreciated.
EDIT:
I've just changed it but it's still not working:
mylist = ("hello", "this", "is", "james")
def firstFunction(x):
return may(lambda: x.upper(), mylist)
print firstFunction()
That isn't an error. It is the function's address in memory. You are seeing it because you didn't invoke the function.
Overall, there are three problems with your code:
You are not invoking the function. Adding (...) after it will do this.
You are not passing in an argument to the function, which it requires.
There is no upper method on a tuple (list in this case is a tuple).
Below is a fixed version of the code that does what I think you want:
# Don't name a variable 'list' -- it overshadows the built-in.
lst = ("hello", "this", "is", "a", "test")
def firstFunction(x):
return tuple(y.upper() for y in x)
print firstFunction(lst)
Output:
('HELLO', 'THIS', 'IS', 'A', 'TEST')
Here are some references on everything done here:
http://docs.python.org/2/reference/compound_stmts.html#function-definitions
https://wiki.python.org/moin/Generators
http://docs.python.org/2.7/library/stdtypes.html#str.upper
While other answers are great, I want to mention that there's already a function in python, called map(), and it does almost exactly what you need:
Apply function to every item of iterable and return a list of the
results..... The iterable
arguments may be a sequence or any iterable object; the result is
always a list.
So you code becomes
print map(str.upper, lst)
or, if you need a tuple, then:
print tuple(map(str.upper, lst))
You don't need anonymous lambda function here, because str.upper() accepts one argument. I think there's a debate about how pythonic this functional programming is, but I personally like it sometimes.
Actually nor the list, nor the tuple has no a method .upper().
So to achieve this you could just execute this statement:
print tuple(x.upper() for x in ("hello", "this", "is", "a", "test"))
http://codepad.org/MZ14yXeV
or this one:
print map(lambda x: x.upper(), ("hello", "this", "is", "a", "test"))
http://codepad.org/kc1LaNCY
list = ("hello", "this", "is", "a", "test")
is a tuple, an immutable, you cannot alter it, use,
print tuple((ele.upper() for ele in list))
I think this is the most pythonic one:
def cap(tup):
return map(str.upper, tup)
>>> tup = ("hello", "this", "is", "a", "test")
>>> cap(tup)
['HELLO', 'THIS', 'IS', 'A', 'TEST']
>>>
What you are trying to do involves list comprehensions:
print [firstFunction(x) for x in list]
what this does is: construct the list whose elements are the result of applying the function
to each of the items in you input list and then printing it.
Some (hopefully helpful) comments
It is bad practice to name a variable list; even though it is not a keyword,
it is the name of a fundamental python type, so re-binding it could cause confusion
elsewhere.
In your definition def firstFunction(list) -- the name list that appears in the
argument list does not have any relationship to the list variable that was defined earlier in your example. You may want to look at this question or the python documentation to understand how the scoping rules work in python.
Related
I have three lists lst_a to lst_c. I would like to write a function that takes each item from the lists, performs a regex search according to lst_b with search group position according to lst_c and replaces the variables in lst_a with the search results.
This is my code:
import re
var_1 = var_2 = var_3 = "replace_me"
lst_a = [
var_1,
var_2,
var_3,
]
lst_b = [
'(foo)(bar)',
'(foo)(bar)(baz)',
'(foo)(baz)(bar)',
]
lst_c = [1, 2, 3]
def lst_search_n_save(variables, regex, position):
global lst_a
global lst_b
for r in regex:
try:
variables = re.search(r, "foobarbaz")
#variables := re.search(r, "foobarbaz") -> not working
print(variables)
print(rf"{variables.group(position)}")
except (AttributeError, TypeError, IndexError):
print("error" + "\n")
variables = "not found"
lst_search_n_save(lst_a, lst_b, lst_c[2])
print(lst_a)
Searching and finding works, but I cannot get the function to save its results into the variables in lst_a. This is what I get instead:
<re.Match object; span=(0, 6), match='foobar'>
error
<re.Match object; span=(0, 9), match='foobarbaz'>
baz
None
error
['replace_me', 'replace_me', 'replace_me']
The expected output for the used positional parameter in my example should be:
print(lst_a)
['not found', 'baz', 'bar']
print(lst_a[1])
baz
First of all, the expected result is not consistent. It would mean that the third regular expression "(foo)(baz)(bar)" would find a match in "foobarbaz", which is not true. So also the third result should be "not found".
Then some remarks on your attempt:
As arguments become local variables, you cannot expect the function to change the global list_a by just assigning to the local variable variables. list_a will not change by running this function.
To overcome the first issue, it would be more fitting to have the function return the list with the three results, and to not pass an argument for that.
Since you want to produce a list, you should not assign a result to variables, but append the results to it, and so build the list you want to return
Avoid global statements. They are not needed here.
Avoid a hard-coded value in your function like "foobarbaz". Instead pass it as argument to the function, so it becomes more flexible.
Not an issue, but although your problem statement speaks of a list_c, your code only ever uses one value from that list. So then it doesn't need to be a list. But I'll leave that part untouched.
I would avoid calling a variable variables, which suggests that this variable contains variables... which makes little sense. Let's call it results.
Here is a correction:
import re
def lst_search_n_save(regex, position, s):
results = []
for r in regex:
try:
match = re.search(r, s)
result = match.group(position)
except (AttributeError, TypeError, IndexError):
result = "not found"
results.append(result)
return results
# Example given in question:
lst_b = ['(foo)(bar)', '(foo)(bar)(baz)', '(foo)(baz)(bar)']
lst_c = [1, 2, 3]
lst_a = lst_search_n_save(lst_b, lst_c[2], "foobarbaz")
print(lst_a) # ['not found', 'baz', 'not found']
I have this following block of code and I am getting this message in the shell...
"function word_switch at 0x102b67a70"
What does this mean and why does Python print this instead of returning the function?
Thanks
D= ['foo', 'bar', 'OMG']
def word_switch (D: list) -> list:
for i in D:
reversed(i)
return word_switch
print(word_switch(D))
You need to generate the reversed list and return it, not the function itself. You can do this
D = ['foo', 'bar', 'OMG']
def word_switch (D: list) -> list:
return ["".join(reversed(i)) for i in D]
#return [i[::-1] for i in D] # Using slicing
print(word_switch(D))
Output
['oof', 'rab', 'GMO']
What does it mean? The output means that the function word_switch lives in that memory position.
Why are you getting it? Because you asked for it. Beware that in the way your function is defined, when you call it you get the function object itself and then you print it.
It happens the very same thing every time you print a function object, for instance:
>>> def f(x):
... x
>>> print f
<function f at 0xb72eda3c>
>>>
If what you want is just reverse a list you can simply use the reverse method of lists objects as suggested in the comments to the OP. It is not necessary to create you own function. If , for some reason, you need your own function then you can write it in the way suggested by #thefourtheye in his answer.
I'm looking for a concise and functional style way to apply a function to one element of a tuple and return the new tuple, in Python.
For example, for the following input:
inp = ("hello", "my", "friend")
I would like to be able to get the following output:
out = ("hello", "MY", "friend")
I came up with two solutions which I'm not satisfied with.
One uses a higher-order function.
def apply_at(arr, func, i):
return arr[0:i] + [func(arr[i])] + arr[i+1:]
apply_at(inp, lambda x: x.upper(), 1)
One uses list comprehensions (this one assumes the length of the tuple is known).
[(a,b.upper(),c) for a,b,c in [inp]][0]
Is there a better way? Thanks!
Here is a version that works on any iterable and returns a generator:
>>> inp = ("hello", "my", "friend")
>>> def apply_nth(fn, n, iterable):
... return (fn(x) if i==n else x for (i,x) in enumerate(iterable))
...
>>> tuple(apply_nth(str.upper, 1, inp))
('hello', 'MY', 'friend')
You can extend this so that instead of one position you can give it a list of positions:
>>> def apply_at(fn, pos_lst, iterable):
... pos_lst = set(pos_lst)
... return (fn(x) if i in pos_lst else x for (i,x) in enumerate(iterable))
...
>>> ''.join(apply_at(str.upper, [2,4,6,8], "abcdefghijklmno"))
'abCdEfGhIjklmno'
I commented in support of your first snippet, but here are a couple other ways for the record:
(lambda (a,b,c): [a,b.upper(),c])(inp)
(Won't work in Python 3.x.) And:
[inp[0], inp[1].upper(), inp[2]]
>>> inp = "hello", "my", "friend"
>>> index = 1
>>> inp[:index] + ( str.upper(inp[index]),) + inp[index + 1:]
('hello', 'MY', 'friend')
Seems simple, the only thing you may need to know is that to make a single element tuple, do (elt,)
Maybe some' like this?
>>>inp = ("hello", "my", "friend")
>>>out = tuple([i == 1 and x.upper() or x for (x,i) in zip(t,range(len(t)))])
>>> out
('hello', 'MY', 'friend')
Note: rather than (x,i) in zip(t, range(len(t))) I should have thought of using the enumerate function : (i,x) in enumerate(t)
Making it a bit more general:
Rather than hard-coding the 1, we can place it in a variable.
Also, by using a tuple for that purpose, we can apply the function to elements at multiple indexes.
>>>inp = ("hello", "my", "friend")
>>>ix = (0,2)
>>>out = tuple([i in ix and x.upper() or x for (i, x) in enumerate(t)])
>>> out
('HELLO', 'my', 'FRIEND')
Also, we can "replace" the zip()/enumerate() by map(), in something like
out = tuple(map(lambda x,i : i == 1 and x.upper() or x, inp, range(len(inp)) ) )
Edit: (addressing comment about specifying the function to apply):
Could be something as simple as:
>>> f = str.upper # or whatever function taking a single argument
>>> out = tuple(map(lambda x,i : i == 1 and f(x) or x, inp, range(len(inp)) ) )
Since we're talking about applying any function, we should mention the small caveat with the condition and if_true or if_false construct which is not exactly a substitute for the if/else ternary operator found in other languages. The limitation is that the function cannot return a value which is equivalent to False (None, 0, 0.0, '' for example). A suggestion to avoid this problem, is, with Python 2.5 and up, to use the true if-else ternary operator, as shown in Dave Kirby's answer (note the when_true if condition else when_false syntax of this operator)
I don't understand if you want to apply a certain function to every element in the tuple that passes some test, or if you would like it to apply the function to any element present at a certain index of the tuple. So I have coded both algorithms:
This is the algorithm (coded in Python) that I would use to solve this problem in a functional language like scheme:
This function will identify the element identifiable by id and apply func to it and return a list with that element changed to the output of func. It will do this for every element identifiable as id:
def doSomethingTo(tup, id):
return tuple(doSomethingToHelper(list(tup), id))
def doSomethingToHelper(L, id):
if len(L) == 0:
return L
elif L[0] == id:
return [func(L[0])] + doSomethingToHelper(L[1:], id)
else:
return [L[0]] + doSomethingToHelper(L[1:], id)
This algorithm will find the element at the index of the tuple and apply func to it, and stick it back into its original index in the tuple
def doSomethingAt(tup, i):
return tuple(doSomethingAtHelper(list(tup), i, 0))
def doSomethingAtHelper(L, index, i):
if len(L) == 0:
return L
elif i == index:
return [func(L[0])] + L[1:]
else:
return [L[0]] + doSomethingAtHelper(L[1:], index, i+1)
i also like the answer that Dave Kirby gave. however, as a public service announcement, i'd like to say that this is not a typical use case for tuples -- these are data structures that originated in Python as a means to move data (parameters, arguments) to and from functions... they were not meant for the programmer to use as general array-like data structures in applications -- this is why lists exist. naturally, if you're needing the read-only/immutable feature of tuples, that is a fair argument, but given the OP question, this should've been done with lists instead -- note how there is extra code to either pull the tuple apart and put the resulting one together and/or the need to temporarily convert to a list and back.
Why is print(x) here not valid (SyntaxError) in the following list-comprehension?
my_list=[1,2,3]
[print(my_item) for my_item in my_list]
To contrast - the following doesn't give a syntax error:
def my_func(x):
print(x)
[my_func(my_item) for my_item in my_list]
Because print is not a function, it's a statement, and you can't have them in expressions. This gets more obvious if you use normal Python 2 syntax:
my_list=[1,2,3]
[print my_item for my_item in my_list]
That doesn't look quite right. :) The parenthesizes around my_item tricks you.
This has changed in Python 3, btw, where print is a function, where your code works just fine.
list comprehension are designed to create a list. So using print inside it will give an error no-matter we use print() or print in 2.7 or 3.x. The code
[my_item for my_item in my_list]
makes a new object of type list.
print [my_item for my_item in my_list]
prints out this new list as a whole
refer : here
It's a syntax error because print is not a function. It's a statement. Since you obviously don't care about the return value from print (since it has none), just write the normal loop:
for my_item in my_list:
print my_item
print in python 3 makes it more obvious on how to use it.
the square brackets in the list comprehension denotes that the output will actually be a list.
L1=['a','ab','abc']
print([item for item in L1])
This should do the trick.
I'm looking to take a string and create a list of strings that build up the original string.
e.g.:
"asdf" => ["a", "as", "asd", "asdf"]
I'm sure there's a "pythonic" way to do it; I think I'm just losing my mind. What's the best way to get this done?
One possibility:
>>> st = 'asdf'
>>> [st[:n+1] for n in range(len(st))]
['a', 'as', 'asd', 'asdf']
If you're going to be looping over the elements of your "list", you may be better off using a generator rather than list comprehension:
>>> text = "I'm a little teapot."
>>> textgen = (text[:i + 1] for i in xrange(len(text)))
>>> textgen
<generator object <genexpr> at 0x0119BDA0>
>>> for item in textgen:
... if re.search("t$", item):
... print item
I'm a lit
I'm a litt
I'm a little t
I'm a little teapot
>>>
This code never creates a list object, nor does it ever (delta garbage collection) create more than one extra string (in addition to text).