And what is it called? I don't know how to search for it; I tried calling it ellipsis with the Google. I don't mean in interactive output when dots are used to indicate that the full array is not being shown, but as in the code I'm looking at,
xTensor0[...] = xVTensor[..., 0]
From my experimentation, it appears to function the similarly to : in indexing, but stands in for multiple :'s, making x[:,:,1] equivalent to x[...,1].
Yes, you're right. It fills in as many : as required. The only difference occurs when you use multiple ellipses. In that case, the first ellipsis acts in the same way, but each remaining one is converted to a single :.
Although this feature exists mainly to support numpy and other, similar modules, it's a core feature of the language and can be used anywhere, like so:
>>> class foo:
... def __getitem__(self, key):
... return key
...
>>> aFoo = foo()
>>> aFoo[..., 1]
(Ellipsis, 1)
>>>
or even:
>>> derp = {}
>>> derp[..., 1] = "herp"
>>> derp
{(Ellipsis, 1): 'herp'}
Documentation here: http://docs.scipy.org/doc/numpy/reference/arrays.indexing.html
It does, well, what you describe it doing.
Related
I am reading Joel Grus's data science from scratch book and found something a bit mysterious. Basically, in some sample code, he wrote
a = [1, 2 ,3 ,4]
xs = [i for i,_ in enumerate(a)]
Why would he prefer to do this way? Instead of
xs = range(len(a))
Answer: personal preference of the author. I find
[i for i, _ in enumerate(xs)]
clearer and more readable than
list(range(len(xs)))
which feels clunky to me. (I don't like reading the nested functions.) Your mileage may vary (and apparently does!).
That said, I am pretty sure I didn't say not to do the second, I just happen to prefer the first.
Source: I am the author.
P.S. If you're the commenter who had no intention of reading anything I write about Python, I apologize if you read this answer by accident.
I looked at the code available on github and frankly, I do not see any other reason for this except the personal preference of the author.
However, the result needs to be a list in places like this:
indexes = [i for i, _ in enumerate(data)] # create a list of indexes
random.shuffle(indexes) # shuffle them
for i in indexes: # return the data in that order
yield data[i]
Using bare range(len(data)) in that part on Python 3 would be wrong, because random.shuffle() requires a mutable sequence as the argument, and the range objects in Python 3 are immutable sequences.
I personally would use list(range(len(data))) on Python 3 in the case that I linked to, as it is guaranteed to be more efficient and would fail if a generator/iterator was passed in by accident, instead of a sequence.
Without being the author, I would have to guess, but my guess is that it's for Python 2 and 3 compatibility.
In Python 2:
>>> a = [1,2,3,4]
>>> xs = range(len(a))
>>> xs
[0, 1, 2, 3]
>>> type(xs)
<type 'list'>
In Python 3:
>>> a = [1,2,3,4]
>>> xs = range(len(a))
>>> xs
range(0, 4)
>>> type(xs)
<class 'range'>
Now, that doesn't make a difference when you're directly iterating over the range, but if you're planning to use the index list for something else later on, the author may feel that the enumerate is simpler to understand than list(range(len(a)))
Both are ok.
When I started coding in python I was more list(range(len(a))) .
Now I am more in pythonic way .
Both are readable.
How would I print a list of strings as their individual variable values?
For example, take this code:
a=1
b=2
c=3
text="abc"
splittext = text.split(text)
print(splittext)
How would I get this to output 123?
You could do this using eval, but it is very dangerous:
>>> ''.join(map(lambda x : str(eval(x)),Text))
'123'
eval (perhaps they better rename it to evil, no hard feelings, simply use it as a warning) evaluates a string as if you would have coded it there yourself. So eval('a') will fetch the value of a. The problem is that a hacker could perhaps find some trick to inject arbitrary code using this, and thus hack your server, program, etc. Furthermore by accident it can perhaps change the state of your program. So a piece of advice is "Do not use it, unless you have absolutely no other choice" (which is not the case here).
Or a less dangerous variant:
>>> ''.join(map(lambda x : str(globals()[x]),Text))
'123'
in case these are global variables (you can use locals() for local variables).
This is ugly and dangerous, because you do not know in advance what a, b and c are, neither do you have much control on what part of the program can set these variables. So it can perhaps allow code injection. As is advertised in the comments on your question, you better use a dictionary for that.
Dictionary approach
A better way to do this is using a dictionary (as #Ignacio Vazquez-Abrams was saying):
>>> dic = {'a':1,'b': 2,'c':3}
>>> ''.join(map(lambda x : str(dic[x]),Text))
'123'
List instead of string
In the above we converted the content to a string using str in the lambda-expression and used ''.join to concatenate these strings. If you are however interested in an array of "results", you can drop these constructs. For instance:
>>> map(lambda x : dic[x],Text)
[1, 2, 3]
The same works for all the above examples.
EDIT
For some reason, I later catched the fact that you want to print the valuesm, this can easily be achieved using list comprehension:
for x in Text :
print dic[x]
again you can use the same technique for the above cases.
In case you want to print out the value of the variables named in the string you can use locals (or globals, depending on what/where you want them)
>>> a=1
>>> b=2
>>> c=3
>>> s='abc'
>>> for v in s:
... print(locals()[v])
...
1
2
3
or, if you use separators in the string
>>> s='a,b,c'
>>> for v in s.split(','):
... print(locals()[v])
...
1
2
3
First of all, I'd like to clarify the question: it's about the slice() function, not slices of lists or strings like a[5:4:3].
The docs mention that this function is used in NumPy and give no examples of usage (it's said how to use it but it's not said when to use it). Moreover, I've never seen this function used in any Python program.
When should one use the slice() function when programming in plain Python (without NumPy or SciPy)? Any examples will be appreciated.
a[x:y:z] gives the same result as a[slice(x, y, z)]. One of the advantages of a slice object is that it can be stored and retrieved later as a single object instead of storing x, y and z.
It is often used to let the user define their own slice that can later be applied on data, without the need of dealing with many different cases.
(Using function semantics) Calling the slice class instantiates a slice object (start,stop,step), which you can use as a slice specifier later in your program:
>>> myname='Rufus'
>>> myname[::-1] # reversing idiom
'sufuR'
>>> reversing_slice=slice(None,None,-1) # reversing idiom as slice object
>>> myname[reversing_slice]
'sufuR'
>>> odds=slice(0,None,2) # another example
>>> myname[odds]
'Rfs'
If you had a slice you often used, this is preferable to using constants in multiple program areas, and save the pain of keeping 2 or 3 references that had to be typed in
each time.
Of course, it does make it look like an index, but after using Python a while, you learn that everything is not what it looks like at first glance, so I recommend naming your variables better (as I did with reversing_slice, versus odds which isn't so clear.
No, it's not all!
As objects are already mentioned, first you have to know is that slice is a class, not a function returning an object.
Second use of the slice() instance is for passing arguments to getitem() and getslice() methods when you're making your own object that behaves like a string, list, and other objects supporting slicing.
When you do:
print "blahblah"[3:5]
That automatically translates to:
print "blahblah".__getitem__(slice(3, 5, None))
So when you program your own indexing and slicing object:
class example:
def __getitem__ (self, item):
if isinstance(item, slice):
print "You are slicing me!"
print "From", item.start, "to", item.stop, "with step", item.step
return self
if isinstance(item, tuple):
print "You are multi-slicing me!"
for x, y in enumerate(item):
print "Slice #", x
self[y]
return self
print "You are indexing me!\nIndex:", repr(item)
return self
Try it:
>>> example()[9:20]
>>> example()[2:3,9:19:2]
>>> example()[50]
>>> example()["String index i.e. the key!"]
>>> # You may wish to create an object that can be sliced with strings:
>>> example()["start of slice":"end of slice"]
Older Python versions supported the method getslice() that would be used instead of getitem(). It is a good practice to check in the getitem() whether we got a slice, and if we did, redirect it to getslice() method. This way you will have complete backward compatibility.
This is how numpy uses slice() object for matrix manipulations, and it is obvious that it is constantly used everywhere indirectly.
From your question I believe you are looking for an example. So here is what I have when I try to slice a list from range(1, 20) with a step of 3
>>> x = range(1, 20)
>>> x[1:20:3]
[2, 5, 8, 11, 14, 17]
>>> x[slice(1, 20, 3)]
[2, 5, 8, 11, 14, 17]
I have three indexes, x,y,t and a tridimensional matrix (it's actually a netcdf variable) in python but the order in which the indexes have to be applied to the matrix change. So, to make it easily user-definable I am trying to get the specific element I want as
order='t,x,y' # or 't,y,x' or anything like this
elem=matrix[eval(order)]
but this fails with TypeError: illegal subscript type. When I try
a=eval(order)
print type(a)
it gives me that a is a tuple, so I'm guessing this is the source of my problem. But why is a a tuple? Any ideas as how to do this? Documentation wasn't helpful.
Also, somehow doing
a=eval(order)
i,j,k=a
elem=matrix[i,j,k]
doesn't work either. Not sure as to why.
EDIT
People are misunderstanding what I'm trying to do here apparently, so let me explain a little better. This is inside a function where the values x, y, t are already defined. However, the order in which to apply those indexes should be provided by the user. So the call would be something like func(order='t,x,y'). That's at least the only way I figured the user could pass the order of the indexes as a parameter. Sorry for the confusion.
Why is a a tuple?
Because it is: if you leave eval() out of the picture, you get the same, when you are just using commas:
>>> a = 1, 2, 3
>>> type(a)
<type 'tuple'>
do instead this:
Give the order directly as list, lists maintain order:
def some_method(order=None):
order = order or [t, y, x]
# t, y, x have to be known out side this scope
...
If your t, x, y are only known within the scope, you - of course - have to
give the order in a symbolic way, thus back to eval. Here you assume knowledge about the inner state of your function
def some_method(order='t,x,y'):
order = eval(order)
...
elem = matrix[order[0]][order[1]][order[2]]
EDIT
wims answer shows how to avoid eval() which should be preferred at least when the input to this function would come from an untrusted source, because eval() would gladly run arbitrary python code.
You should try to avoid using eval for this. It's hacky and ugly, and it's easily possible to avoid it just by making a lookup dict.
>>> order = 'x,y,t' # this is specified outside your function
You can still pass this string into your function if you want:
>>> # this is inside your function:
>>> t,x,y = 0,1,2 # I don't know what your actual values are..
>>> lookup = {'t': t, 'x': x, 'y': y} # make this inside your function
>>> tuple_ = tuple(lookup[k] for k in order.split(','))
>>> tuple_
(1, 2, 0)
Now use the tuple_ to index your array.
I think what you're looking for is called "slicing", or even "extended slicing", depending on the data format you're slicing. Oh, and you don't need eval for that at all, tuples would do just fine.
See also this question:
Explain Python's slice notation
Consider:
operator.add(a, b)
I'm having trouble understanding what this does. An operator is something like +-*/, so what does operator.add(a, b) do and how would you use it in a program?
Operator functions let you pick operations dynamically.
They do the same thing as the operator, so operator.add(a, b) does the exact same thing as a + b, but you can now use these operators in abstract.
Take for example:
import operator, random
ops = [operator.add, operator.sub]
print(random.choice(ops)(10, 5))
The above code will randomly either add up or subtract the two numbers. Because the operators can be applied in function form, you can also store these functions in variables (lists, dictionaries, etc.) and use them indirectly, based on your code. You can pass them to map() or reduce() or partial, etc. etc. etc.
As operator.add is a function and you can pass argument to it, it's for the situations where you can not use statements like a+d, like the map or itertools.imap functions. For better understanding, see the following example:
>>> import operator
>>> from itertools import imap
>>> list(imap(operator.add,[1,3],[5,5]))
[6, 8]
It does the same, it's just a function version of the operator in the Python operator module. It returns the result, so you would just it like this:
result = operator.add(a, b)
This is functionally equivalent to
result = a + b
It literally is how the + operator is defined. Look at the following example
class foo():
def __init__(self, a):
self.a = a
def __add__(self, b):
return self.a + b
>>> x = foo(5)
>>> x + 3
8
The + operator actually just calls the __add__ method of the class
The same thing happens for native Python types,
>>> 5 + 3
8
>>> operator.add(5,3)
8
Note that since I defined my __add__ method, I can also do
>>> operator.add(x, 3)
8
For the first part of your question, checkout the source for operator.add. It does exactly as you'd expect; adds two values together.
The answer to part two of your question is a little tricky.
They can be good for when you don't know what operator you'll need until run time. Like when the data file you're reading contains the operation as well as the values:
# warning: nsfw
total = 0
with open('./foo.dat') as fp:
for line in fp:
operation, first_val, second_val = line.split()
total += getattr(operator, operation)(first_val, second_val)
Also, you might want to make your code cleaner or more efficient (subjective) by using the operator functions with the map built-in as the example shows in the Python docs:
orig_values = [1,2,3,4,5]
new_values = [5,4,3,2,1]
total = sum(map(operator.add, orig_values, new_values))
Those are both convoluted examples which usually means that you probably won't use them except in extraordinary situations. You should really know that you need these functions before you use them.