Parsing slice information from a slice object? - python

I'm trying to get the information from a slice. Here's the start of my function. (I have tried "elif isinstance(key, slice):" for the fourth line and can't get that to work)
def __getitem__(self, key):
if isinstance(key,(int, long)):
#do stuff if an int
elif #item is slice
#do stuff if a slice
If I make a function call of obj[4:6] to call this function and I print the "key" variable in the function, it prints "slice(4,6, None)"
How do I parse the 4 and 6 values? What I"m trying to do is be able to use the data from the list inside the function.

>>> slice(4,5).start
4
>>> slice(4,5).stop
5
>>> slice(4,5).step #None
One particularly useful method of the slice object is the indices method:
>>> slice(4,5).indices(12)
(4, 5, 1)
You might use it like this:
for i in range(*my_slice.indices(len(self))):
print self[i]
Note that this really shines with negative indices or steps:
>>> slice(4,-5).indices(12)
(4, 7, 1)
>>> print range(*slice(None,None,-1).indices(12))
[11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

If you want the info from the slice object, access its attributes start, stop, and step. These attributes are documented here.

Related

Create list of class variables from list of objects

Tricky to word the title well.
I want to create a list of values that correspond to the variables of a list of objects. It can be inelegently done like this;
class Example:
def __init__(self, x):
self.x = x
objlist = [ Example(i) for i in range(10) ]
DESIRED_OUTCOME = [ obj.x for obj in objlist ]
But this seems unpythonic and cumbersome, so I was wondering if there is a way of indexing all the the values out at one time.
Im wondering if there is a syntax that allows me to take all the variables out at once, like pulling a first axis array from a 2d array;
ex = example2darray[:,1] #2d array syntax
OUTCOME = objlist[:, objlist.x] #Is there something like this that exists?
>>> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I hope this question makes sense
Nothing unpythonic about that, IMO, but if you really want to iterate over the x values of your instances 'directly' instead of obtaining them from the object itself, you can map them to operator.attrgetter:
import operator
objlist = [Example(i) for i in range(10)]
DESIRED_OUTCOME = map(operator.attrgetter("x"), objlist)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Beware that on Python 3.x map() returns an iterator so if you want the a list result make sure to turn it into one. Also, unless you construct Example in a special way, pretty much anything will be slower than the good old list comprehension loop which you consider 'inelegant'.

Use unknown number of variables to place the returns of a method

I have a method __some_method which might return one parameter, or two, or any number. I want to call this method in another one and place the returns into variables, like so
var1, var2 ... varN = self.__some_method()
Is there any way that one can do this, in a very general setting, such that it works for any number of returned parameters?
I still think a dictionary is the best way to solve what you are trying to do. However, this does not go without saying that you should probably revise why it is you have a function that could return an indeterminate amount of variables. That seems like a bad decision. At the very least that return should be collected inside a data structure, so you know that you will have a single return type where you can deal with the contents yourself.
With that being said. If you are looking for some kind of way where you can assign names to these individual variables that will come back, you can make use of a dictionary to control this. Here is an example:
def foo(*args):
return args
result = foo(1, 2, 3, 4, 5, 6, 7, 8)
var_pack = {'var_{}'.format(idx): data for idx, data in enumerate(result, 1)}
print(var_pack)
# {'var_7': 7, 'var_4': 4, 'var_8': 8, 'var_2': 2, 'var_3': 3, 'var_6': 6, 'var_1': 1, 'var_5': 5}
print(var_pack['var_8'])
# 8

Slices with several intervals?

I have a file where I want to extract columns 2, 3, 4, 5 and column -4. These columns are not adjacent.
For reasons of code neatness I'd like to do something like
values = line.split()[columns_to_extract]
instead of
values_part_one = line.split()[columns_to_extract_one]
values_part_two = line.split()[columns_to_extract_two]
Therefore I'd like to make a slice that contains the positions 2, 3, 4, 5 and -4 to be able to extract the values in one line. Is this possible?
If not, are there any other neat oneliners that could do this?
Is it possible to make a slice to do that? No.
However, all is not lost! You can use operator.itemgetter:
getter = operator.itemgetter(2, 3, 4, 5, -4)
example:
>>> import operator
>>> getter = operator.itemgetter(2, 3, 4, 5, -4)
>>> getter(range(50)) # Note, returns a `tuple`
(2, 3, 4, 5, 46)
parts = line.split()
values_part_one = [parts[i] for i in columns_to_extract_one]
values_part_two = [parts[i] for i in columns_to_extract_two]
or, as #mgilson points out, you could use operator.itemgetter to get tuples:
import operator
extract_one = operator.itemgetter(*columns_to_extract_one) # or list explicitly
extract_two = operator.itemgetter(*columns_to_extract_two) # if using fixed cols
parts = line.split()
values_part_one = extract_one(parts)
values_part_Two = extract_two(parts)
Note that both of these will fail with IndexError if the thing you are trying to grab from isn't large enough to contain all of the specified indices.

Does Python select a 'default' tuple item/index?

Imagine the following function:
def getMinAndMax(numbers):
return min(numbers), max(numbers)
What will happen if I do this?
num = getMinAndMax([1,2,3,4,5])
Will num assume the value of the first item in the tuple, min, or will something else happen? I know I can just try it, but I'm looking for some defined Python behavior here.
Your function returns the two-element tuple min([1, 2, 3, 4, 5]), max([1, 2, 3, 4, 5]) which evaluates to 1, 5. So the statement
num = getMinAndMax([1,2,3,4,5])
will bind the name num to the tuple (1, 2) and you can access the individual values as num[0] and num[1]. Python does allow you, though, to use what's usually referred to as a unpacking assignment which looks like this:
nmin, nmax = getMinAndMax([1, 2, 3, 4, 5])
That binds each name to a succeeding element of the tuple on the right-hand side and allows you to use the values without indexing. If you need a tuple of the results your formulation is simplest, though of course the expression (nmin, nmax) will re-create it from the second one.
num will be a tuple. The value of num will be equal to (1,5) in your example. Python does not check types by default, so you can safely assign whatever value of whatever type you want to whatever variable.

Short Python Code to say "Pick the lower value"?

What I mean is,
I'm looking for really short code that returns the lower value.
for example:
a=[1,2,3,4,5,6,7,8,9,10]
b=[1,2,3,4,5,6,7,8]
len(a) = 10
len(b) = 8
if (fill-this-in):
print(lesser-value)
And I forgot to add that if b is lower than a, I want b returned - not len(b) - the variable b.
print(min(a, b))
You're not hugely clear about what you want, so some alternatives. Given the following two lists:
a = [1,2,3,4,5,6,7,8,9,10]
b = [1,2,3,4,5,6,7,8]
To print the shortest list, you can just do..
>>> print(min(a, b))
[1, 2, 3, 4, 5, 6, 7, 8]
To get the shortest length as an number, you can either min the len() of each list, or do len(min()) (both are identical, choose which ever you find most readable)..
>>> print(min( len(a), len(b) ))
# or..
>>> print(len( min(a, b) ))
8
To print the lowest value in either list, you can supply the list as a single argument to min()
>>> a.extend(b) # Appends b to a
>>> print a
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8]
>>> print(min(a))
1
Finally, another possibility, the list that has the lowest values in total:
>>> max( sum(a), sum(b) )
55
To print the actual list with the highest sum(), you could either use the ternary operator, like..
>>> print a if sum(a) > sum(b) else b
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
..although I never really liked (or use) it, instead using the slight longer, regular if/else statements..
>>> if sum(a) > sum(b):
... print a
... else:
... print b
...
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
If the length of the list is what makes it lower (not its values), then you actually want:
min(a, b, key=len)
which is only incidentally equivalent to
min(a, b)
in the given example.
min() should accomplish what you need
print(min(a,b))
It seems this answer may now be out of date. I just had this same question and found this answer, but wasn't getting the results I expected. Turns out Min doesn't automatically return the shorter of the two lists (in 2.7). To get that you have to use the 'key' argument (introduced in 2.5)(emphasis added):
min(iterable[, key]) min(arg1, arg2, *args[, key]) Return the smallest
item in an iterable or the smallest of two or more arguments.
If one positional argument is provided, iterable must be a non-empty
iterable (such as a non-empty string, tuple or list). The smallest
item in the iterable is returned. If two or more positional arguments
are provided, the smallest of the positional arguments is returned.
The optional key argument specifies a one-argument ordering function
like that used for list.sort(). The key argument, if supplied, must be
in keyword form (for example, min(a,b,c,key=func)).
Changed in version 2.5: Added support for the optional key argument
So in this example, although it seems to work (and still would in 2.7), it only does because the list of integers is the same. However if these were two different non-ordered lists then:
min(a,b)
would return the list with the lowest first integer.
To be sure to get the shorter of two lists, use:
min(a,b, key=len)
heads up, min(a, b, key=len) only works in python 2.5 and up I think.
(it's not working on my macbook with python 2.4, but my linux server with 2.5 is fine)
Is the following what you want?
if len(a) < len(b):
print a
else:
print b
Alternatively, if you want to use the ternary operator like #Andrew G. Johnson:
print a if len(a) < len(b) else b
PS. Remember that Python does not use braces for its blocks, and that its ternary operator is different from C-like languages.
I don't know Python but for something like this I'd use a ternary operator.
print(length(a) < length(b) ? length(a) : length(b))
One thing to note about this that if they are equal it will print length(b)

Categories

Resources