用代码说话。
-
-
Save xxleyi/8547c07b0ab63f33c0defe85069ef45b to your computer and use it in GitHub Desktop.
accepted version:
class SortedList(list):
def __init__(self, values):
super().__init__(sorted(values))
x = SortedList([1, 9, 7])
print(x)
my version:
class SortedList(list):
def __init__(self, values):
super().__init__(values)
super().sort()
x = SortedList([1, 3, 2])
print(x)
自觉我的版本更优雅 :-)
Swap Values
In other languages:
temp = a
a = b
b = temp
In Python:
b, a = a, b
Perhaps you've seen this before. But do you know how it works?
- The comma is the tuple constructor syntax.
- A tuple is created on the right (tuple packing).
- A tuple is the target on the left (tuple unpacking).
The right-hand side is unpacked into the names in the tuple on the left-hand side.
Use in
where possible (2)
But .keys()
is necessary when mutating the dictionary:
for key in list(d.keys()):
d[str(key)] = d[key]
list(d.keys())
creates a static list of the dictionary keys. Otherwise, you'll get an exception "RuntimeError: dictionary changed size during iteration".
Dictionary setdefault
Method (1)
Here we have to initialize mutable dictionary values. Each dictionary value will be a list. This is the naïve way:
Initializing mutable dictionary values:
equities = {}
for (portfolio, equity) in data:
if portfolio in equities:
equities[portfolio].append(equity)
else:
equities[portfolio] = [equity]
dict.setdefault(key, default)
does the job much more efficiently:
equities = {}
for (portfolio, equity) in data:
equities.setdefault(portfolio, []).append(equity)
dict.setdefault()
is equivalent to "get, or set & get". Or "set if necessary, then get". It's especially efficient if your dictionary key is expensive to compute or long to type.
The only problem with dict.setdefault()
is that the default value is always evaluated, whether needed or not. That only matters if the default value is expensive to compute.
If the default value is expensive to compute, you may want to use the defaultdict
class, which we'll cover shortly.
Dictionary setdefault
Method (2)
Here we see that the setdefault
dictionary method can also be used as a stand-alone statement:
setdefault
can also be used as a stand-alone statement:
navs = {}
for (portfolio, equity, position) in data:
navs.setdefault(portfolio, 0)
navs[portfolio] += position * prices[equity]
The setdefault
dictionary method returns the default value, but we ignore it here. We're taking advantage of setdefault
's side effect, that it sets the dictionary value only if there is no value already.
from collections import defaultdict
equities = defaultdict(list)
for (portfolio, equity) in data:
equities[portfolio].append(equity)
given = ['John', 'Eric', 'Terry', 'Michael']
family = ['Cleese', 'Idle', 'Gilliam', 'Palin']
pythons = dict(zip(given, family))
# do this: # not this:
if x: if x == True:
pass pass
# do this: # not this:
if items: if len(items) != 0:
pass pass
# and definitely not this:
if items != []:
pass
Truth Values
The True
and False
names are built-in instances of type bool
, Boolean values. Like None
, there is only one instance of each.
False True
False
(== 0)
True
(== 1)
""
(empty string)
any string but ""
(" "
, "anything"
)
0
, 0.0
any number but 0
(1, 0.1, -1, 3.14)
[]
, ()
, {}
, set()
any non-empty container ([0]
, (None,)
, ['']
)
None
almost any object that's not explicitly False
>>> items = 'zero one two three'.split()
>>> print items
['zero', 'one', 'two', 'three']
- or -
i = 0
for item in items: for i in range(len(items)):
print i, item print i, items[i]
i += 1
for (index, item) in enumerate(items):
print index, item
# compare: # compare:
index = 0 for i in range(len(items)):
for item in items: print i, items[i]
print index, item
index += 1
Default Parameter Values
This is a common mistake that beginners often make. Even more advanced programmers make this mistake if they don't understand Python names.
def bad_append(new_item, a_list=[]):
a_list.append(new_item)
return a_list
Rule of thumb:
- Use a list comprehension when a computed list is the desired end result.
- Use a generator expression when the computed list is just an intermediate step.
Here's a recent example I saw at work.
➔
We needed a dictionary mapping month numbers (both as string and as integers) to month codes for futures contracts. It can be done in one logical line of code.
➔
The way this works is as follows:
- The
dict()
built-in takes a list of key/value pairs (2-tuples). - We have a list of month codes (each month code is a single letter, and a string is also just a list of letters). We enumerate over this list to get both the month code and the index.
- The month numbers start at 1, but Python starts indexing at 0, so the month number is one more than the index.
- We want to look up months both as strings and as integers. We can use the
int()
andstr()
functions to do this for us, and loop over them.
Recent example:
month_codes = dict((fn(i+1), code) for i, code in enumerate('FGHJKMNQUVXZ') for fn in (int, str))
month_codes
result:
{ 1: 'F', 2: 'G', 3: 'H', 4: 'J', ... '1': 'F', '2': 'G', '3': 'H', '4': 'J', ...}
EAFP vs. LBYL
It's easier to ask forgiveness than permission
Look before you leap
Generally EAFP is preferred, but not always.
- Duck typing
If it walks like a duck, and talks like a duck, and looks like a duck: it's a duck. (Goose? Close enough.)
- Exceptions
Use coercion if an object must be a particular type. If x
must be a string for your code to work, why not call
str(x)
instead of trying something like
isinstance(x, str)
EAFP try/except
Example
You can wrap exception-prone code in a try/except
block to catch the errors, and you will probably end up with a solution that's much more general than if you had tried to anticipate every possibility.
try:
return str(x)
except TypeError:
...
Note: Always specify the exceptions to catch. Never use bare except
clauses. Bare except
clauses will catch unexpected exceptions, making your code exceedingly difficult to debug.
Moral: don't use wild-card imports!
Packages
package/
__init__.py
module1.py
subpackage/
__init__.py
module2.py
Simple is Better Than Complex
Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.
—Brian W. Kernighan, co-author of The C Programming Language and the "K" in "AWK"
In other words, keep your programs simple!
python - Rewrite to dictionary comprehensions - Stack Overflow
优化一下:
再优化一下:
最好的方式: