Does python have one way of doing things? - python

I have always seen in python articles/books that python is simple and it has only one way of doing things. I would like someone to explain to me this concept keeping in mind the example below, if I wanted to get the min and max values of sequence I would do the following;
seq=[1,2,3,4,5,6]
min(seq) #1
max(seq) #6
but I can also do this;
seq[:1] #1
seq[-1] #6
surely this are two ways of doing one simple thing. This confuses me a bit.

Not that it "has one way of doing things" as more "There should be one-- and preferably only one --obvious way to do it." (from Zen of Python).
This doesn't exclude possibility of having more than one way of doing things. We're talking about programming where creativity is one of the most important skills and finding new ways of solving problems is a must.
In your example you're doing two different things:
getting minimum and maximum of the list
getting first and the last element of the list
it happens that in this particular case result is exactly the same.

Those are two different things. max() gives you the largest element of the list (using regular number comparison by default), while [-1] gives you the last element – in your example, this happens to be the same thing. But consider this:
>>> seq = [2, 7, 5, 4]
>>> max(seq)
7
>>> seq[-1]
4
BTW, seq[:1] gives you something different again – namely [1] (or [2] in my example), a one-element list. What you probably meant was seq[0], which is the first element of the list, compared to min(seq), the smallest one.

One obvious way.
>>> import this

In your example, you actually do two different things -- they just happen to give the same result, because your input list is sorted. However, there's always multiple ways of doing things. Python's approach isn't really to avoid or forbid multiple ways of doing the same thing, but have one - and preferably only one - obvious way of doing things.

max(), min() and index slicing they all do different things. In your list, the order may not be sorted like your example, so using slicing will not get the max/min for you in those cases. if you want to get max/min values, just use max()/min() functions

There is always more than one way to solve a problem, but the python developers try not to add language features that offer redundant functionality, which is very unlike perl.

Related

How a for in loop in python ends when there is no update statement in it? [duplicate]

This question already has an answer here:
How does the Python for loop actually work?
(1 answer)
Closed 3 months ago.
For example:
#1
val = 5
for i in range(val) :
print(i)
When the range is exhausted i.e. last value reached how python knows for in loop ends . As in other languages
#2
for(i=0;i<=5;i++){
print(i)
}
As in this exp. when i's values becomes larger than 5 false condition leads to termination of loop .
I tried reading docs of python and browsed over google but no satisfying answer. So unable to get a picture of this .
So this is actually a complicated question, but the very rough version of the answer is "the compiler/interpreter can do what it wants".
It isn't actually running the human-readable text you write at all - instead it goes through a whole pipeline of transformations. At minimum, a lexer converts the text to a sequence of symbols, and then a parser turns that into a tree of language constructs; that may then be compiled into machine code or interpreted by a virtual machine.
So, the python interpreter creates a structure that handles the underlying logic. Depending on the optimizations performed (those are really a black box, it's hard to say what they do), this may be producing structures logically equivalent to what a Java-like for loop would make, or it could actually create a data structure of numbers (that's what the range() function does on its own) and then iterate over them.
Editing to give some more foundation for what this construct even means:
Python iteration-style loops are different in how they're defined from C-style i++ sorts of loops. Python loops are intended to iterate on each element of a list or other sequence data structure - you can say, for instance, for name in listOfNames, and then use name in the following block.
When you say for i in range(x), this is the pythonic way of doing something like the C-style loop. Think of it as the reverse of
for(int i = 0; i < arr.length(); i++){
foo(arr[i[)
}
In that code block you're accessing each element of an indexible sequence arr by going through each valid index. You don't actually care about i - it's just a means to an end, a way to make sure you visit each element.
Python assumes that's what you're trying to do: the python variant is
for elem in arr:
foo(elem)
Which most people would agree is simpler, clearer and more elegant.
However, there are times when you actually do want to explicitly go number by number. To do that with a python style, you create a list of all the numbers you'll want to visit - that's what the range function does. You'll mostly see it as part of a loop statement, but it can exist independently - you can say x = range(10), and x will hold a list that consists of the numbers 0-9 inclusive.
So, where before you were incrementing a number to visit each item of a list, now you're taking a list of numbers to get incrementing values.
"How it does this" is still explanation I gave above - the parser and interpreter know how to create the nitty-gritty logic that actually creates this sequence and step through it, or possibly transform it into some logically equivalent steps.

Is there a function to check proper string inclusion relationship in python? [duplicate]

I know that if we would like to know whether string a is contained in b we can use:
a in b
When a equals to b, the above express still returns True. I would like an expression that would return False when a == b and return True when a is a substring of b. So I used the following expression:
a in b and a != b
I just wonder is there a simpler expression in Python that works in the same way?
Not sure how efficient direct string comparisons are in Python, but assuming they are O(n) this should be reasonably efficient and still readable :
len(a) < len(b) and a in b
Likes the other answers it's also O(n), but the length operation should be O(1). It should also be better suited for edge cases (e.g. a being bigger than b)
This is going to be a short answer, but it is what it is. What you have is enough.
While there might be other alternatives, the way you did it is easy enough to understand, simple and more readable than anything else (of course this is subjective to each and everyone). IMO a simpler expression in Python that works in the same way doesn't exist. That's just my personal perspective on this subject. I'm usually encouraged to follow KISS:
The KISS principle states that most systems work best if they are kept
simple rather than made complicated; therefore simplicity should be a
key goal in design and unnecessary complexity should be avoided.
As an example, the other answer it's not any different from the explicit and, and the chaining can be confusing when used with in and == because many people will see that as (a1 in b) != a1, at least at first glance.
b.find(a) > 0 or b.startswith(a) and len(b) > len(a)
I'm not saying this is the best answer. It's just another solution. The OP's statement is as good as any. The accepted answer is also good. But this one does work and demonstrates a different approach to the problem.

Does a trailing comma after an n-tuple in Python change its value?

This is a very basic doubt that came to my mind. When we use threading module in python to start a new thread, I have see two different ways in which arguments are passed to with the call:
Version 1:
thread = threading.Thread(target=tar,args=(4,0.25,))
Version 2:
thread = threading.Thread(target=tar,args=(4,0.25))
The difference is the addition of , at the end of argument list at the end of version 1 call. Both the versions work fine but I want to know if theres any significant difference between the two versions above and if than which ones a better way to write? If theres no difference than what is the reason a lot of people and articles choose to use version 1 and add a redundant , at the end of the argument list.
The two forms of writing a 2-tuple are equivalent. Proof:
>>> (4,0.25,) == (4,0.25)
True
For an elaboration on valid tuple syntax in Python, see https://wiki.python.org/moin/TupleSyntax. Specifically:
In Python, multiple-element tuples look like:
1,2,3
The essential elements are the commas between each element of
the tuple. Multiple-element tuples may be written with a trailing
comma, e.g.
1,2,3,
but the trailing comma is completely optional.

Most efficient way to check if any substrings in list are in another list of strings

I have two lists, one of words, and another of character combinations. What would be the fastest way to only return the combinations that don't match anything in the list?
I've tried to make it as streamlined as possible, but it's still very slow when it uses 3 characters for the combinations (goes up to 290 seconds for 4 characters, not even going to try 5)
Here's some example code, currently I'm converting all the words to a list, and then searching the string for each list value.
#Sample of stuff
allCombinations = ["a","aa","ab","ac","ad"]
allWords = ["testing", "accurate" ]
#Do the calculations
allWordsJoined = ",".join( allWords )
invalidCombinations = set( i for i in allCombinations if i not in allWordsJoined )
print invalidCombinations
#Result: set(['aa', 'ab', 'ad'])
I'm just curious if there's a better way to do this with sets? With a combination of 3 letters, there are 18278 list items to search for, and for 4 letters, that goes up to 475254, so currently my method isn't really fast enough, especially when the word list string is about 1 million characters.
Set.intersection seems like a very useful method if you need the whole string, so surely there must be something similar to search for a substring.
The first thing that comes to mind is that you can optimize lookup by checking current combination against combinations that are already "invalid". I.e. if ab is invalid, than ab.? will be invalid too and there's no point to check such.
And one more thing: try using
for i in allCombinations:
if i not in allWordsJoined:
invalidCombinations.add(i)
instead of
invalidCombinations = set(i for i in allCombinations if i not in allWordsJoined)
I'm not sure, but less memory allocations can be a small boost for real data run.
Seeing if a set contains an item is O(1). You would still have to iterate through your list of combinations (with some exceptions. If your word doesn't have "a" it's not going to have any other combinations that contain "a". You can use some tree-like data structure for this) to compare with your original set of words.
You shouldn't convert your wordlist to a string, but rather a set. You should get O(N) where N is the length of your combinations.
Also, I like Python, but it isn't the fastest of languages. If this is the only task you need to do, and it needs to be very fast, and you can't improve the algorithm, you might want to check out other languages. You should be able to very easily prototype something to get an idea of the difference in speed for different languages.

Python index like MATLAB's end/2

MATLAB has a very convenient syntax for getting half of a list:
x(1:end/2)
The syntax I know for python to do this is
x[:len(x)/2]
This is fine in this case, because len(x) is easy to write. But this syntax becomes more than a pain when the name of the list is long (as they sometimes need to be), and even more so when there is a list of similar long names.
I know this is a real shot in the dark, but does python have any syntax option like MATLAB's?
There is no specialized syntax. If you need to do it a lot, write a function:
def half_list(l):
return l[:len(l)/2]
No, lists in python don't have the concept end( a somewhat similar concept is the index -1).
An easy (but not recommended) solution to your problem is:
l = longnamelist
l[:len(l)/2]
or to copy/paste the long name... (some editors have a shortcut for copying a word, this makes copy/paste of a long name very easy.)

Categories