One of my students found that, for ell (a list of string) and estr (a string), the following expression is True iff a member of ell is contained in estr:
any(t in estr for t in ell)
Can anyone explain why this is syntactically legal, and if so what does the comprehension generate?
This is a generator expression.
func_that_takes_any_iterable(i for i in iterable)
It's like a list comprehension, but a generator, meaning it only produces one element at a time:
>>> a = [i for i in range(10)]
>>> b = (i for i in range(10))
>>> print(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print(b)
<generator object <genexpr> at 0x7fb9113fae40>
>>> print(list(b))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> print(list(b))
[]
When using a generator expression in isolation, the parentheses are required for syntax reasons. When creating one as an argument to a function, the syntax allows for the extra parentheses to be absent.
Most functions don't care what type of iterable they're given - list, tuple, dict, generator, etc - and generators are perfectly valid. They're also marginally more memory-efficient than list comprehensions, since they don't generate the entire thing up front. For all() and any(), this is especially good, since those methods short-circuit as soon as they would return False and True respectively.
As of python 3.8, the syntactic restrictions for the walrus operator := are similar - in isolation, it must be used inside its own set of parentheses, but inside another expression it can generally be used without them.
This is syntactically legal because it's not a list. Anything of the form (x for x in array) is a generator. Think of it like lazy list, which will generate answer only when you ask.
Now generator are also an iterable so it's perfectly fine for it to be inside an any() function.
willBeTrue = any(True for i in range(20))
So this will basically generate 20 Trues and any function looks for any true value; thus will return True.
Now coming to your expression:
ans = any(t in estr for t in ell)
This {t in estr} returns a boolean value. Now generator makes len(ell) amount of those boolean value and any thinks good.. since atleast one is true I return True.
Related
Is there something like a map function in Excel?
For example, let's say I want to apply the formula ABS to a list of items. Something like:
=ABS,{-1,2,3,4,5}
As an example of python-like notation:
# list comprehension
>>> [abs(i) for i in [-1,2,3,4,5]]
[1, 2, 3, 4, 5]
# map
>>> map(abs,[-1,2,3,4,5])
[1, 2, 3, 4, 5]
# passing arbitrary function
>>> map(lambda x:abs(x)+1, [-1,2,4,5,6])
[2, 3, 5, 6, 7]
Is there something similar in Excel?
Note, the closest I've gotten is using native operators against lists, such as =2*{1,2,3,4,5}, but this just gives things like the basic arithmetic operations.
In Excel-365 you can directly use ABS() function with array of data. Try-
=ABS({-1,2,3,4,5})
You can use the MAP function in Excel with a similar notation to other languages. Note however, that you must pass it a LAMBDA function, not just an in-line formula. Here then would be your answer:
=MAP({-1,2,3,4,5},LAMBDA(x, ABS(x)))
Why two zip objects (made using same two iterables) aren't equal?
list1 = [1, 2, 3, 4]
list2 = [5, 6, 7, 8]
a = zip(list1, list2)
b = zip(list1, list2)
print(a == b)
The above code is printing False.
Shouldn't it give `True' since the zip objects are similar?
The returned zip object is an iterator. To be able to test the value equality of it, potentially the entire iterator would need to be walked, which would exhaust it, so you'd never be able to use it after. And if only part of the iterator was walked during the test, it would be left in a "difficult to determine state", so it wouldn't be usable there either.
I'm not sure if zip is considered to be a "user-defined class", but note this line in the docs:
User-defined classes have __eq__() and __hash__() methods by default; with them, all objects compare unequal (except with themselves)
In theory they could have made a workaround that would allow equality testing of a zip object (in cases where the object that was zipped wasn't itself an iterator), but there was likely no need. I can't think of a scenario where you would need to test such a thing, and where comparing the object forced as a list isn't an option.
Simple problem.
I've got these lists:
alpha = [5,10,1,2]
beta = [1,5,2]
gamma = [5,2,87,100,1]
I thought I could sort them all with:
map(lambda x: list.sort(x),[alpha,beta,gamma])
Which doesn't work.
What is working though is:
a,b,c = map(lambda x: list.sort(x),[alpha,beta,gamma])
Can someone explain why I need to define a,b and c for this code to work?
Because map() is lazy (since Python 3). It returns a generator-like object that is only evaluated when its contents are asked for, for instance because you want to assign its individual elements to variables.
E.g., this also forces it to evaluate:
>>> list(map(lambda x: list.sort(x),[alpha,beta,gamma]))
But using map is a bit archaic, list comprehensions and generator comprehensions exist and are almost always more idiomatic. Also, list.sort(x) is a bit of an odd way to write x.sort() that may or may not work, avoid it.
[x.sort() for x in [alpha, beta, gamma]]
works as you expected.
But if you aren't interested in the result, building a list isn't relevant. What you really want is a simple for loop:
for x in [alpha, beta, gamma]:
x.sort()
Which is perfectly Pythonic, except that I maybe like this one even better in this fixed, simple case:
alpha.sort()
beta.sort()
gamma.sort()
can't get more explicit than that.
Its is because list.sort() returns None. It sorts the list in place
If you want to sort them lists and return it do this:
a,b,c = (sorted(l) for l in [alpha, beta, gamma])
In [10]: alpha.sort()
In [11]: sorted(alpha)
Out[11]: [1, 2, 5, 10]
I saw this code on my textbook:
double :: (Num a) => a -> a
double x = x * 2
map (double.double) [1,2,3,4]
What I don't get is that if functional composition operation have the highest priority, why use parentheses to include double.double? If I remove those parentheses, I get error message. So what's exactly is functional composition's priority?
All of the built-in operators' respective precedences and fixities can be found in the Haskell Report section 4.4.2. In particular, . and !! have precedence 9, which is the highest among operators. However, function application is not an operator. Function application is specifically designed to have precedence higher than any operator, so
map (double.double) [1,2,3,4]
This is applying the function double . double to each element of the list [1, 2, 3, 4]
map double.double [1,2,3,4]
This is attempting to compose the functions map double and double [1, 2, 3, 4], which is unlikely to be successful (though it is not technically impossible).
Precedence (and associativity) are ways of resolving the ambiguity between multiple infix operators in an expression. If there are two operators next to an operand, precedence (and associativity) tells you which of them takes the operand as an argument and which of them takes the other applied-operator expression as an argument. For example, in the expression 1 + 2 * 3, the 2 is next to both + and *. The higher precedence of * means that * gets the 2 as its left argument, while + takes the whole 2 * 3 sub-expression as its right argument.
However that's not the case in map double.double [1, 2, 3, 4]. There's only one operator, with two operands on either side, so there's no question for precedence to answer for us. The two operands are map double and double [1, 2, 3, 4]; operands are sequences of one or more terms, not only the immediate left and right terms. Where there's more than one term the sequence is parsed as simple chained function application (i.e. a b c d is ((a b) c) d).
Another way to think of it is that there is an "adjacency operator" which has higher precedence than can be assigned to anything else, and is invisibly present between any two non-operator terms (but not anywhere else). In this way of thinking map double.double [1, 2, 3, 4] is really something like map # double . double # [1, 2, 3, 4] (where I've written this "adjacency operator" as #). Since # has higher precedence than ., this is (map # double) . (double # [1, 2, 3, 4]).1
Whichever way you choose to interpret it, there is a simple consequence. It is simply impossible for any applied operator expression to be passed as an argument in non-operator function application unless there are parentheses around the operator application. If there is an operator in an expression outside any parentheses, then the outermost layer of the expression is always going to be an operator application.
1 This adjacency operator explanation seems to be pretty common. I personally think it is a poor explanation for how to parse expressions, since you need to partially parse an expression to know where to insert the adjacency operators.
It's often called the "whitespace operator", which is even more confusing since not every piece of whitespace represents this operator, and you don't always need whitespace for it to be there. e.g. length"four" + 1
Sometimes I need to pass an operator as a closure, like this:
do.some.thing() { x,y -> x+y }
I'm wondering if there is any shorthand "operator pointer" syntax, analogous to the "method pointer" syntax, that would give me the operator already wrapped into a two-argument closure.
I see that most arithmetic operators are available as methods on Number and related classes:
public Number plus(Number right)
Add two numbers and return the result.
but they are instance methods and I can't figure out if I can use the method pointer operator .& to turn them into a two-argument closure.
You can do this sort of thing as well...
Not sure uncurry is the right term, but it's almost right ;-)
import org.codehaus.groovy.runtime.MethodClosure
def uncurry(MethodClosure c) {
{a, ...b -> a."$c.method"(*b) }
}
Then, to make a 2 arg closure from Number.plus, you can do:
def plus = uncurry(Number.&plus)
And then:
assert plus(1, 2) == 3
Which also works with other method handles as well:
def collate = uncurry(List.&collate)
assert collate([1, 2, 3, 4, 5], 2, true) == [[1, 2], [3, 4], [5]]
No, there's no such operator.
The method pointer operator won't work because the MethodClosure it creates basically has an object, in this case the Number class, and a method name. So if you do...
def c = Number.&plus
Then calling c will attempt to call plus() on the Number class, which of course won't work.
The only shortcut I can think of is to declare your operator closures once and simply reuse them as needed.