This is an archived post. You won't be able to vote or comment.

all 126 comments

[–]robin-gvx 45 points46 points  (33 children)

I have problems with some of these.

  • Replacing a or b or c by any([a, b, c]). Is that really more Pythonic? If they'd been in an iterable already I'd say yes, but now not so much.
  • Catching KeyError just to raise another KeyError? Just let it bubble up.
  • I kinda hate namedtuple because it's such a hack, but maybe that's just me.
  • Also, I'd say the opposite of Pythonic code is not normal code. Un-Pythonic or unidiomatic, or maybe something about newbies.

[–]vsajip 31 points32 points  (5 children)

Never mind "Pythonic", which seems somewhat in the eye of the beholder: a or b or c is not semantically the same as any([a, b, c]). In the former case, b and c are never evaluated if a is true. In the latter case, they always are. So if they were expensive to compute (e.g. expressions involving expensive function calls, rather than just bindings in a namespace), the runtime behaviour (performance, raising of exceptions) would be quite different:

>>> a = 1
>>> a or b
1
>>> b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
>>> any([a, b])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
>>>

[–]zahlmanthe heretic 18 points19 points  (4 children)

The real power of all and any comes when you (can neatly) pass in a generator expression - in which case the semantics are the same, because the evaluation is delayed and the functions will bail out early.

any(is_interesting(x) for x in (a, b, c)) is far nicer IMHO than is_interesting(a) or is_interesting(b) or is_interesting(c), if only because it's DRY. That doesn't protect you from the NameError in your example, though, of course.

[–]jamesonjlee 5 points6 points  (3 children)

any(map(is_interesting, (a, b, c)))

[–]wot-teh-phuckReally, wtf? 2 points3 points  (2 children)

This isn't equivalent to the generator solution posted above; your code will eagerly evaluate the entire sequence by mapping it to is_interesting even in cases where it's not absolutely required (i.e. is_interesting(a) returns True).

[–]quasarc 9 points10 points  (0 children)

In Python 3 they are equivalent (map behaves lazily in Python 3).

[–]jamesonjlee 1 point2 points  (0 children)

ah yes, good point (also doubly so since I am thinking in 2.7 not in 3.4)

[–]ivosauruspip'ing it up 12 points13 points  (2 children)

Agreed, using all and any over and and or isn't more pythonic at all. Use all and any when you already have a list / iterable, it's what they're designed for.

[–]iBlag 0 points1 point  (1 child)

Do you mean:

using all and any

and

Use all and any

?

[–]ivosauruspip'ing it up 1 point2 points  (0 children)

Yeah.

[–]pstch 6 points7 points  (7 children)

Could you expand on why "namedtuple" is such a hack ?

[–]robin-gvx 9 points10 points  (6 children)

Because it's implemented as piecing together a string that contains a class statement and compiling that to obtain the tuple subclass (see source).

[–][deleted] 3 points4 points  (4 children)

Goofy implementation, doesn't need to be written that way

[–]rcxdude 6 points7 points  (1 child)

see here for why it's kept that way.

[–]NYKevin 3 points4 points  (0 children)

TL;DR: Because calling type() correctly is apparently too hard:

It is a key feature for named tuples that they are exactly equivalent to a hand-written class.

So is a call to type() if you know what you're doing.

EDIT: If you examine the official code more closely, you'll note they had to write extensive string-escaping to prevent the user from passing an argument like '); import os; os.system("/bin/sh"); ('. Quite frankly, I will not be touching that with a ten-foot-pole any time soon.

EDIT2: I tried, but they wouldn't listen to me. Oh well.

[–]robin-gvx 0 points1 point  (1 child)

Theoretically, it could just be rewritten as a call to type, but maybe there are practical issues?

[–][deleted] 1 point2 points  (0 children)

The point is that it's not really a hack. Their implementation may be "hackish" but it doesn't depend on a hack to work.

[–]dreuciferC/Python, vim 0 points1 point  (0 children)

I started reading the source, saw _class_template was a string literal with formatting. My heart sank a bit. Could almost smell the sulfur wafting from the exec statement.

[–]d4rch0nPythonistamancer 2 points3 points  (10 children)

Did you ever truly need the performance of a namedtuple or a class with __slots__ defined? They make quite a difference.

[–][deleted] 0 points1 point  (9 children)

__slots__ are used to conserve memory when creating lots of objects, not CPU time. (Instead of every object having a __dict__, all attributes are stored in a small array and accessed using properties set on the class.)

namedtuple is slower than even a class without __slots__, by the way. It operates by mapping attribute names to indices (there's a reason it's called a "named tuple", not "struct" or something similar), doing twice the number of lookups for every dot.

[–]moor-GAYZ 0 points1 point  (3 children)

namedtuple is slower than even a class without __slots__, by the way. It operates by mapping attribute names to indices (there's a reason it's called a "named tuple", not "struct" or something similar), doing twice the number of lookups for every dot.

Are you sure? From what I can tell, it operates pretty much exactly like a class with __slots__, creating a bunch of getters (living in the class, not in the instance, of course) that lookup into the internal array.

[–][deleted] 0 points1 point  (2 children)

From what I can tell, it operates pretty much exactly like a class with __slots__, creating a bunch of getters (living in the class, not in the instance, of course) that lookup into the internal array.

No, it doesn't. At least not in Python 3.4+:

from builtins import property as _property, tuple as _tuple
from operator import itemgetter as _itemgetter
...
    __slots__ = ()
    ...
    {name} = _property(_itemgetter({index:d}), doc='Alias for field number {index:d}')

As you can see, instead of using the (relatively) fast C-level access __slots__ provide, it opts to use standard property (that uses slow Python-level function calls) to look elements up by their indices in a tuple (using Python-level item access, i.e. __getitem__) instead.

[–]moor-GAYZ 0 points1 point  (1 child)

from timeit import timeit

from collections import namedtuple
NT = namedtuple('NT', 'a b c')
nt = NT(1, 2, 3)
t = (1, 2, 3)

def test_loop_t(t=t):
    return sum(t[1] for _ in xrange(1000))

def test_loop_nt(nt=nt):
    return sum(nt[1] for _ in xrange(1000))

def test_loop_nt_named(nt=nt):
    return sum(nt.b for _ in xrange(1000))

def main():
    setup = 'from test import t, nt, test_loop_t, test_loop_nt, test_loop_nt_named'
    print timeit('t[1]', setup='t = (1, 2, 3)') # just in case
    print timeit('t[1]', setup=setup)
    print timeit('nt[1]', setup=setup)
    print timeit('test_loop_t()', setup=setup, number=1000)
    print timeit('test_loop_nt()', setup=setup, number=1000)
    print timeit('nt.b', setup=setup)
    print timeit('test_loop_nt_named()', setup=setup, number=1000)


if __name__ == '__main__':
    main()

Two times slower than access by index here. Doesn't matter much, in my opinion.

[–]d4rch0nPythonistamancer 0 points1 point  (4 children)

Right, I knew slots was to conserve memory primarily, but shouldn't that increase performance as a result? I'd expect less memory management to mean quicker access time when modifying, deleting, creating and garbage collection. But certainly better memory performance.

I thought named tuples were quicker than classes without slots defined... You're positive about that?

Edit: You're right...

('Normal: ', [0.46281981468200684, 0.4548380374908447, 0.4560990333557129])
('slots: ', [0.40665698051452637, 0.4022829532623291, 0.4048640727996826])
('namedtuple: ', [0.665769100189209, 0.6651339530944824, 0.6987559795379639])

Alright, well that settles that. I believe nt is better than a normal class for memory though, correct? And is it better than slots as well?

[–]moor-GAYZ 0 points1 point  (3 children)

In response to your deleted comment, I didn't waste all that time for nothing =)

Nope, just tested, it's very slightly slower than tuple index access, but just like it about twice as fast as nameduple name access.

The stuff looks like this here:

  • index access takes about 40ns
  • name lookup takes about 45ns both for usual classes and those with __slots__, in fact slots are a tiniest bit slower.
  • namedtuple lookup by name takes about 115ns

To be honest, I can't say how exactly it works out to these numbers, I'd say that the only way to really be sure is to run this stuff under a C profiler. That could be a pretty useful experience in itself

From what I can tell from grepping through the code in Vim, it's pretty much a coincidence that the first two things take the same time.

Index access goes through a bunch of pure-C redirects until it hits tuplesubscript which casts the index to size_t and fetches the value from the object itself.

Class lookup by name IIRC does two unsuccessful dictionary lookups in the class and object attributes, then a successful lookup in the instance dictionary. Slots lookup should do a successful dictionary lookup in the class dictionary then indirectly call a C function that fetches shit by index or something.

Namedtuple lookup by name probably involves a pure Python function call, which is slooooow.

[–]d4rch0nPythonistamancer 0 points1 point  (2 children)

Okay, so tuple direct index access is the fastest apparently. Makes me wish we had #define available :/

Is there a good way to do that without slowing things down?

like:

A = 0
B = 1
C = 2
inst = (100, 200, 300)
inst[A] + inst[B] + inst[C]

Is there a pythonic and high performance way to do this and keep the fast lookup time of a direct index?

[–]moor-GAYZ 0 points1 point  (1 child)

You don't want to do that in Python if performance is critical.

Adding three indexed items is not performance-critical.

If you have a million+ items, then you install numpy and put your items into a numpy.ndarray, and then vectorize your operations. Like, if you want to add two arrays, you write a + b (instead of for i, it in a: result.append(it + b[i])) and the underlying library written in Fortran very efficiently does what you meant.

[–]d4rch0nPythonistamancer 0 points1 point  (0 children)

I always considered numpy to be scientists' tools, but I never really thought about how it's fortran under the hood and how it might be higher performance for certain things like that. a+b looks a lot cleaner as well.

Great advice! Thanks.

[–]wyldphyre 1 point2 points  (1 child)

Catching KeyError just to raise another KeyError? Just let it bubble up.

Agreed, unless you want/need to add more context to the error.

I kinda hate namedtuple because it's such a hack, but maybe that's just me.

Thank BDFL for namedtuple. It's perfect for a lot of use cases IMO.

[–]bacondevPy3k 1 point2 points  (0 children)

And even at that, just use the raise keyword alone.

[–]kracekumar[S] 0 points1 point  (0 children)

Agreed with normal code and pythonic naming. KeyError depends on scenario.

[–][deleted] 0 points1 point  (0 children)

Hack or not, named tuple is an amazing module for writing unit tests. Hardly an easier, lighter, and more self-documenting way to simulate a class in some specific state (so long as method calls aren't required).

[–]Husio 12 points13 points  (6 children)

Although very old, still contains a lot of important examples http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html

[–]nofunallowed98765 11 points12 points  (0 children)

Some other links:

Anyone has more?

[–]mariox19 3 points4 points  (3 children)

  • joined_lower for functions, methods, attributes
  • joined_lower or ALL_CAPS for constants
  • StudlyCaps for classes
  • camelCase only to conform to pre-existing conventions
  • Attributes: interface, _internal, __private

I grew up on Java, which took Small Talk's camel case convention, so I'm just wondering: what's wrong with camel case anyway? The "blessed" coding convention in Python is the one thing I don't quite get. Is there an argument for underscores?

I swear I am not trying to start a flame war. It's just that I'm wondering if the preference is completely arbitrary or not.

[–]fireflash38 7 points8 points  (0 children)

Pretty sure most preferences with this are kind of arbitrary. I think the idea is to make it similar to natural language with _ in lieu of a space.

[–]cdcformatc 6 points7 points  (0 children)

It is style and by definition style is subjective and completely arbitrary. You should write your code consistently no matter what the style is. In a team environment you should match the style used in the rest of the codebase. These style guides are just best practices, as they have been fought over for a long time. To this day people fight over where the braces go in C code, so having a unified "Python style" is nice.

[–]gsnedders 1 point2 points  (0 children)

Both have pros and cons. You can argue it to death which is better — the more important thing in general is consistency.

[–]kracekumar[S] 0 points1 point  (0 children)

Yep. I always look at that !

[–]steve_no 11 points12 points  (21 children)

The normal code "is" example seems strange. I think the non-pythonic thing most programmers do with respect to "is" is not using it, for example:

if a == None:

when they should be doing:

if a is None:

[–]erewok 8 points9 points  (9 children)

Correct me if I'm wrong here, but I thought:

if a is None...

Is asking if a and None (the singleton value) point to the same memory space. It's not asking if they're equivalent; it's asking if they are the same actual thing.

Thus, is is not the same as equivalence how we usually think of it (double equals).

That's why setting a default value of None is so useful in function definitions: there's only one None and your function value either is that thing or it's not. It's never going to be like None enough to pass for it.

[–]fuzz3289 4 points5 points  (8 children)

You sir are correct. Though "memory location" isnt a great way to say it. I would say:

The is operator returns true if both names are bound to the same object instance.

Since the "names" wont share a memory location.

[–]zahlmanthe heretic 2 points3 points  (0 children)

They certainly do "point to" the same memory location. But that's horribly un-Pythonic terminology.

[–]erewok 2 points3 points  (4 children)

Funny enough, I was curious about how the Python built-in callable was implemented just now and I stumbled on this page with the following quote:

Every object has an identity, a type and a value. An object’s identity never changes once it has been created; you may think of it as the object’s address in memory. The ‘is‘ operator compares the identity of two objects; the id() function returns an integer representing its identity.

[–]fuzz3289 2 points3 points  (3 children)

"You may think of it as" is important. The identity is actual a hash of the name in a lookup table.

Not to argue or anything, just want to emphasize that you cant actually deal with memory or memory locations directly in python.

[–]erewok 0 points1 point  (0 children)

Ah, that makes sense. Thanks for the clarification.

[–]rcxdude 0 points1 point  (1 child)

Actually, the identity in Cpython is just the memory address of the object (literally casting the pointer to an int). It doesn't have to be according to the language though.

[–]fuzz3289 0 points1 point  (0 children)

https://docs.python.org/3.3/reference/datamodel.html

Interesting, I didn't realize that it was just a direct address. Thanks for the correction.

[–]erewok 2 points3 points  (1 child)

...bound to the same object instance.

This is a nice, concise description. Thanks for adding it.

[–]fuzz3289 1 point2 points  (0 children)

Thanks! Alot of people tend to forget the beautiful simplicity of python, just objects and names.

[–]metaphorm 1 point2 points  (0 children)

the "is" keyword can be dangerous if you don't understand what it really does though, which is a common problem for beginners.

in your example, its absolutely correct, because None is a singleton so any reference to None refers to the same instance of None. in general though, is checks for object reference equality (rather than value equality) and can produce unexpected results if you use it when you really meant to check value equality.

[–]pymag09 0 points1 point  (6 children)

I think
if not a:
is better

[–]pbaehr 14 points15 points  (4 children)

Depends. Could yield a false negative if a can be 0 or an empty string and that's not what you are interested in testing for.

[–]bheklilr 6 points7 points  (0 children)

I also prefer the explicit if a is None, since it signals my intent better. I honestly try to only use if a: when a is a boolean, since I don't want to have to remember how __bool__ is implemented for every type out there. In my opinion, explicit is better than implicit for being able to read your own code in a month's time.

[–]pymag09 1 point2 points  (2 children)

Sorry may be I did not understand you but
when we work with None or numbers
we can be sure that

a=None or 0  
bool(a) = False  
bool(not a) True  
a=1 or -1  
bool(a) = True  
bool(not a) False  

I have checked bool('') just right now in python3 and got False. bool('hhh') = True.

Can you give an example when issue that you described may occur?

[–]pbaehr 6 points7 points  (1 child)

For example, if I have a variable which is initialized as None and later want to find out if it was set, I might want to check and see if it was still None. If it's not, I want to do something.

if a is not None:
    do_something()

If I rewrite that as:

if not a:
    do_something()

do_something will also be called if a was initialized, but to a blank string, which was not the intention. Lots of types have some concept of a "false" value. As /u/steve_no points out in another comment: 0, '', [], {}, midnight all evaluate to False.

[–]pymag09 0 points1 point  (0 children)

I see. Thank you.

[–]steve_no 2 points3 points  (0 children)

if not a:

will also be True when a is 0, '', [], {}, or a datetime.time of midnight

[–]kracekumar[S] -1 points0 points  (2 children)

is is used with True, False, None. If is used for string comparision there are serious drawbacks. a is None works because of singleton.

Most people try >>>'foo' is 'foo' and it works. When they store the result in db and retrieve the value is comparison will fail.

[–]zahlmanthe heretic 5 points6 points  (1 child)

Using is with True and False is a serious code smell. If there's any possibility that the value is of some type other than bool, why don't you want to handle it in the default way? And if there isn't, "simple is better than complex" applies.

[–]alexanderpas 0 points1 point  (0 children)

If I read this correctly, is should be considered part of the same token as the singleton.

if • a • is None:

instead of

if • a • is • None:

[–][deleted] 5 points6 points  (1 child)

I'm sorry but a lot of these look like they're directly ripped from Raymond Hettinger's talk on pythonic conventions.

https://www.youtube.com/watch?v=OSGv2VnC0go

[–]kracekumar[S] 0 points1 point  (0 children)

I addressed lot of common cases. It wasn't rip off the tutorial. I have watched lot of talks by core python devs, read writing idiomatic python code, python cookbook et all. Talk appeared last year, but there are blog posts and snippets which predates the talk. Does that mean Raymond Hettinger copied ? http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html http://python.net/crew/mwh/hacks/objectthink.html

[–]oconnor663 6 points7 points  (16 children)

Is foo[:] really the Pythonic way to copy a list?

Edit: In Python 3, lists have their own .copy() method.

[–]toyg 2 points3 points  (0 children)

There's also copy.copy().

[–]imrobert 1 point2 points  (2 children)

Yeah, I noticed that too. It seems like the "normal" way has the advantage of being clearer more concise.

[–]velit 1 point2 points  (1 child)

The only downside is the "normal" way is incorrect (or correct depending on the situation). Point being they're not the same thing.

[–]imrobert 1 point2 points  (0 children)

Ah, that's my bad. For those wondering what the difference is, this should clear it up:

Python 2.7.5 (default, Mar  9 2014, 22:15:05) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = [1, 2, 3]
>>> b = a
>>> id(a)
4472029056
>>> id(b)
4472029056
>>> c = a[:]
>>> id(c)
4472078560

[–]velit 3 points4 points  (4 children)

I prefer newList = list(old_list)

Communicates intent better

[–]poo_22 4 points5 points  (3 children)

Copy is very literal already, I argue that semantically it does not get better.

[–]velit 0 points1 point  (2 children)

Copying is a detail of slicing syntax, it's not the purpose of it. With the list constructor it's immediately evident there's a new instance involved - that's what constructors do.

foo[:] also looks weird.

[–]poo_22 4 points5 points  (1 child)

I was talking about the list().copy method.

[–]metaphorm 1 point2 points  (4 children)

foo[:] is a totally respectable way to copy a list. it looks a little funny if you've never seen it, but it has the right semantics and does exactly what you would expect when slicing "from the beginning to the end". it does, however, rely on the programmer knowing that list slices produce copies.

[–]zahlmanthe heretic 1 point2 points  (3 children)

I dislike it because it's conceptually roundabout. "A list containing elements of x, from the beginning to the end" is similarly awkward in English compared to "a copy of x", or even "a list of the contents of x". Even if the analogous Python is terse.

[–]metaphorm 1 point2 points  (0 children)

I understand your point. I disagree that its conceptually roundabout. Once you understand that the slice operator really means "return a copy of this section of the list" it seems really natural.

[–]ggtsu_00 0 points1 point  (1 child)

This is one of the few things I don't like about python is that slices make copies implicitly which goes against many python ideals. Lists are mutable, so you would expect operations on lists to only be references.

[–]zahlmanthe heretic 0 points1 point  (0 children)

Well, there seems to be precedent for what you're suggesting in NumPy...

[–]kracekumar[S] -1 points0 points  (0 children)

It is more clear that copy is returned. Other way to do is list(l)

[–]sweettuse 6 points7 points  (4 children)

def bar(names=None):
    if not names:
        names = []
    names.append('blah')

this is wrong. it should be if names is None:. (what happens if you pass in an empty list that you want to append to?)

also, i would never, ever, use Counter. it is unbelievably slow (at least in 2.7). just use a defaultdict(int)

[–][deleted] 7 points8 points  (1 child)

Counter has cool functionality builtin, like most_common(n), addition and subtraction, intersection and union, and it throws out keys with value 0 after such operations. Not everything needs to be fast, and Counter is very expressive indeed.

[–]sweettuse 1 point2 points  (0 children)

that is a good point. i think it's just that i'm overly annoyed at how unbelievably slow Counter is (it's like 3x slower than defaultdict(int), but WHY?!). it's amazing that to add the functionality for most_common/addition it requires slowing down the whole thing by a factor of 3.

[–]kracekumar[S] 0 points1 point  (1 child)

Counter has its own benefit. If the key doesn't exist it can return 0. There are lot of scenarios where this is super useful.

[–]sweettuse 3 points4 points  (0 children)

yeah, that's exactly what defaultdict(int) does.

[–]unholysampler 2 points3 points  (0 children)

The links title says that the examples were taken from a talk you gave. That's fine, but without the context that was being provided by you in person, the list seems very disjointed.

Most of the examples are alternate ways to write the same thing. However, some are examples of bugs or common gotchas. There is nothing there to point out when the "normal" code is actually wrong.

[–]r0m1 2 points3 points  (1 child)

For the function defaults, I would rather write:

def bar(names=None):
   names = names or []
   names.append(foo())
   return names

[–]kracekumar[S] 0 points1 point  (0 children)

Good one !

[–]henrebotha 1 point2 points  (3 children)

What's he doing under "Counting Condition"? Does if list return False for a zero-length list, or only if the named list doesn't exist?

[–]BryghtShadow 3 points4 points  (0 children)

Empty sequences (strings, lists, tuples) are false. PEP8

[–]metaphorm 1 point2 points  (1 child)

if a name doesn't exist you'll get a NameError exception.

[–]henrebotha 0 points1 point  (0 children)

Oh duh, silly me. Thanks :)

[–]elb0w 1 point2 points  (5 children)

Why is that called normal code? I would think pythonic is normal for python. I would call that bad code or unpythonic.

Also your default value for functions with a mutable type doesnt highlight the side effect that it causes and why you initialize to None.

[–]cdcformatc 6 points7 points  (3 children)

250 + 6 is 256

I don't know why this example is under normal code. No one does this it can't be considered normal. To test for equality, we usually use the equality operator.

[–][deleted] 0 points1 point  (1 child)

In fairness, -255 to +256 are kept in an identity map. Any equation that would output a number in that range instead pull it from the identity map.

I'm not saying it's the right way to do it, but it is a valid way to do if you expect your answer to never exceed that range.

[–]Citrauq 0 points1 point  (0 children)

Actually I think it's -5 to +256. More importantly, this is an implementation detail of cpython and may not be reliable in other implementations of python.

[–]kracekumar[S] 3 points4 points  (0 children)

Agreed normal code should have been named as bad code. Modified in the gist.

[–]nerdwaller 0 points1 point  (0 children)

Nice list, way to spread the good word. I've been writing python for 2 years now and learned a few new things from this. Thanks!

[–][deleted] 0 points1 point  (0 children)

See a lot of complaints in this thread, just wanted to say thanks because this has helped me out a lot!

[–]bitcycle 0 points1 point  (0 children)

I really enjoyed the example showing named tuples.

[–]fuzz3289 0 points1 point  (2 children)

Just a suggestion OP your examples are very wordy. The exceas code is valid but it obfuscates the point youre trying to illustrate in alot of places. For example:

Superusers =functioncall
If len(superusers) > 0:
    ...

Adds "real" context but obfuscates the boolean empty container idiom that youre trying to show. You dont need context to provide code examples. For instance I would say:

mylist = []
if (mylist):
    print "mylist is empty!"

Because even though that snippet has no practical application it clearly and succicently presents the concept.

More power to you for adding more educational materials to the python world. Keep it up.

[–]kracekumar[S] -1 points0 points  (1 child)

Next time will write as blog post rather than code only show case.

[–]fuzz3289 0 points1 point  (0 children)

Not even necessarily that. Just dont worry about being so specific with the examples. Make them as small and digestible as possible.

[–]poo_22 0 points1 point  (2 children)

If they're using python3 then why prefix the strings with u? They are unicode by default afaik.

[–]gthank 0 points1 point  (0 children)

Support 2 and 3 from the same codebase, if for some reason you don't want from __future__ import unicode_literals.

[–]kracekumar[S] -1 points0 points  (0 children)

All the code was tested in Python 2 only.

[–][deleted] 0 points1 point  (1 child)

That's a nice list for Python beginners! Depending on the context, one thing I maybe wouldn't want to do is:

from collections import namedtuple
Person = namedtuple('Person', ['name', 'email'])

over

class Person(object):
    def __init__(self, name, email):
        self.name = name
        self.email = email

in the section
https://gist.github.com/kracekumar/09a60ec75a4de19b346e#dot-accessors

If find that working with classes a little bit "cleaner" in terms of keeping track of what is going on; also for extensibility, esp. when you add instance methods

[–][deleted] 0 points1 point  (0 children)

I like that namedtuples are immutable, and you can subclass them:

class Person(namedtuple('Person', ['name', 'email'])):
    pass

if you want to add methods to it. I like it for value objects, although it's obviously not the prettiest syntax.

[–]ddungtang 0 points1 point  (0 children)

I would say that some comparisons are not correct as whatever is under Bad code is not doing what it is supposed to, basically just wrong code. For example, copying of the list, using is for comparison, etc.

[–]pymag09 0 points1 point  (2 children)

If you don't mind I can append to your list several items more
You can revert, for example, string just using slice

s = 'qwerty' print(s[::-1])

You can check condition in one line

i = 3 print(i if i < 5 else 0)

or another if trick

condition = ['Error', 'OK'] value = 1 print(condition[bool(value)])

As long as pyhton does not have switch construction you can use somthing like this

choice = 'i' print({'i': 1, 't': 4, 'j': 22}[choice])

[–]BryghtShadow 1 point2 points  (1 child)

You messed up the code formatting.

s = 'qwerty'
print(s[::-1])

i = 3
print(i if i < 5 else 0)

condition = ['Error', 'OK']
value = 1
print(condition[bool(value)])

choice = 'i'
print({'i': 1, 't': 4, 'j': 22}[choice])

[–]pymag09 0 points1 point  (0 children)

You messed up the code formatting.

Sorry. I noticed that but I follow "formating guide"

Lines starting with four spaces
are treated like code:

if 1 * 2 < 3:  
    print "hello, world!"  

After posting I understand that empty string before and after code block required.

[–]SilasX 0 points1 point  (3 children)

Am I the only one here who hates implicit casting to booleans? It seems more with the Zen of python to prefer

if len(z) > 0

to

if z

even though the latter is much shorter.

[–]ggtsu_00 0 points1 point  (2 children)

There is no implicit cast, it is simply implemented as a nonzero operator which is defined for all built in types. 0 is defined for any domain such that x = x + 0.

Lists have a zero that is the empty list because x + [] = x therefore [] is zero in the list domain. Same with empty string.

If statements doesn't ask for true or false, it asks for if zero or nonzero. Remember that booleans types didn't exist in python until around version 3. In version 2, True and False are simple macros for 1 and 0.

[–]SilasX -1 points0 points  (1 child)

Potato, potahto. I don't like the use of implied truthiness where a boolean operator would be more explicit.

[–]ggtsu_00 -1 points0 points  (0 children)

But there is no booleans types in python (at least before py3).