日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

python入门必备10个坑_适合 Python 初学者的一些技巧和坑

發布時間:2023/11/27 生活经验 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python入门必备10个坑_适合 Python 初学者的一些技巧和坑 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

前幾天董大 @董偉明 的愛派森上線了,還發了一套 PPT 和視頻,PPT 共有75頁干貨,講了很多進階的用法,也包括很多坑,非常適合剛入門的同學,免得再踩到。

這里我提取部分非常規的,也就是大部分教程里沒有的,加入自己的理解,同時語法改為 Python 3,也爭取延伸一些,就當是做筆記了。

設置全局變量

有時候設置全局變量的需求并不是直接賦值,而是想從某個數據結構里引用生成,可以用下面這兩種方法,推薦第二種,golbals() 支持字典用法很方便。

1

2

3

4

5

6

7

8

9

10

11

12

13

14>>>d = {'a': 1, 'b':2}

>>># 粗暴的寫法

>>>for k, v in d.items():

... exec "{}={}".format(k, v)

...

>>># 文藝的寫法

>>>globals().update(d)

>>>a, b

(1, 2)

>>>'a', 'b'

('a', 'b')

>>>globals()['a'] = 'b'

>>>a

'b'

字符串格式化

用 format 方法可以支持很多種格式,這里就不多說了,可以看官方文檔。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16>>>"{key}={value}".format(key="a", value=10) # 使?命名參數

'a=10'

>>>"[{0:<10}], [{0:^10}], [{0:*>10}]".format("a") # 左中右對?

'[a ], [ a ], [*********a]'

>>>"{0.platform}".format(sys) # 成員

'darwin'

>>>"{0[a]}".format(dict(a=10, b=20)) # 字典

'10'

>>>"{0[5]}".format(range(10)) # 列表

'5'

>>>"{0!r:20}".format("Hello")

"'Hello' "

>>>"{0!s:20}".format("Hello")

'Hello '

>>>"Today is: {0:%a %b %d %H:%M:%S %Y}".format(datetime.now())

'Today is: Mon Mar 31 23:59:34 2014'

列表去重

這里講了兩種方法,正常情況下 set 是更好的選擇;

(注:這里董大視頻講解有誤,方法一單位是1.1微妙,是慢于956納秒,我也自己測試了,確實兩種情況都不如 set)

1

2

3

4

5

6

7

8

9

10

11

12

13

14>>>l = [1, 2, 2, 3, 3, 3]

>>>list({}.fromkeys(l).keys()) # 利用構建字典鍵去重

[1, 2, 3] # 列表去重(1)

>>>list(set(l)) # 常見set函數去重

[1, 2, 3]

In [2]: %timeit list(set(l))

1000000 loops, best of 3: 956 ns per loop

In [3]: %timeit list({}.fromkeys(l).keys())

1000000 loops, best of 3: 1.1 μs per loop

In [4]: l = [random.randint(1, 50) for i in range(10000)]

In [5]: %timeit list(set(l))

1000 loops, best of 3: 271 μs per loop

In [6]: %timeit {}.fromkeys(l).keys()

1000 loops, best of 3: 310 μs per loop

操作字典

字典是 Python 很常用的數據結構,各種函數和方法要掌握。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15>>>dict((["a", 1], ["b", 2])) # ?兩個序列類型構造字典

{'a': 1, 'b': 2}

>>>dict(zip("ab", range(2)))

{'a': 0, 'b': 1}

>>>dict(map(None, "abc", range(2)))

{'a': 0, 'c': None, 'b': 1}

>>>dict.fromkeys("abc", 1) # ?序列做 key,并提供默認 value

{'a': 1, 'c': 1, 'b': 1}

>>>{k:v for k, v in zip("abc", range(3))} # 字典解析

{'a': 0, 'c': 2, 'b': 1}

>>>d = {"a":1, "b":2}

>>>d.setdefault("a", 100) # key 存在,直接返回 value 1

>>>d.setdefault("c", 200) # key 不存在,先設置,后返回 200

>>>d

{'a': 1, 'c': 200, 'b': 2}

對字典進行邏輯操作

只能先轉成鍵值對列表再進行操作,然后轉回去;

(注:這里原文是 Python 2 中 viewitems 方法,已經被 items 替代)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18>>>d1 = dict(a = 1, b = 2)

>>>d2 = dict(b = 2, c = 3)

>>>d1 & d2 # 字典不?支持該操作

Traceback (most recent call last):

File "", line 1, in

TypeError: unsupported operand type(s) for &: 'dict' and 'dict'

>>>v1 = d1.items()

>>>v2 = d2.items()

>>>dict(v1 & v2) # 交集

{'b': 2}

>>>dict(v1 | v2) # 并集

{'a': 1, 'b': 2, 'c': 3}

>>>dict(v1 - v2) #差集(僅v1有,v2沒有的)

{'a': 1}

>>>dict(v1 ^ v2) # 對稱差集 (不會同時出現在 v1 和 v2 中)

{'a': 1, 'c': 3}

>>>('a', 1) in v1 #判斷

True

vars

vars() 的作用是返回對象的屬性和屬性值的字典對象,如果沒有參數,就打印當前調用位置的屬性和屬性值,類似 locals()。

1

2

3

4>>>vars() is locals()

True

>>>vars(sys) is sys.__dict__ # 可用于找類屬性

True

實現上下文管理類

可以用來自動關閉 DB 連接

1

2

3

4

5

6

7

8

9

10

11

12

13>>>import pymongo

>>>class Operation(object):

... def __init__(self, database,

... host='localhost', port=27017):

... self._db = pymongo.MongoClient(

... host, port)[database]

... def __enter__(self):

... return self._db

... def __exit__(self, exc_type, exc_val, exc_tb):

... self._db.connection.disconnect()

...

>>>with Operation(database='test') as db:

... print db.test.find_one()

contextlib

這個模塊主要包含一個裝飾器 contextmanager ,作用是可以省去像上面那樣改寫魔術魔法,也能實現同樣的類

1

2

3

4

5

6

7

8

9

10>>>@contextlib.contextmanager

...def operation(database, host='localhost',

port=27017):

... db = pymongo.MongoClient(host, port)[database]

... yield db

... db.connection.disconnect()

...

>>>import pymongo

>>>with operation('test') as db:

... print(db.test.find_one())

包的構建

如果包里有一些模塊不想被 import * 這樣引用,可以用 __all__ 把允許被引用的放進去;

__all__ = ["add", "x"]

某些時候,包內的文件太多,需要分類存放到多個目錄中,但?不想拆分成新的包或子包。這么做是允許的, 只要在 __init__.py 中? __path__ 指定所有子目錄的全路徑即可 (子目錄可放在包外),下面這段代碼可以自動指定子目錄。

1

2

3

4from os.path import abspath, join

subdirs = lambda *dirs: [abspath(

join(__path__[0], sub)) for sub in dirs]

__path__ = subdirs("a", "b")

slots

限制給類實例綁定屬性,大量屬性時減少內存占用

1

2

3

4

5

6

7

8

9

10

11

12

13>>>class User(object):

... __slots__ = ("name", "age")

... def __init__(self, name, age):

... self.name = name

... self.age = age

...

>>>u = User("Dong", 28)

>>>hasattr(u, "__dict__")

False

>>>u.title = "xxx"

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'User' object has no attribute 'title'

@cached_property

主要實現的功能是,被裝飾的類實例方法在第一次調用后,會把值緩存下來,下次再調用會直接從 __dict__ 取結果,避免了多次計算;你可以參考下面的代碼實現這個裝飾器。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15>>>class cached_property(object):

... # from werkzeug.utils import cached_property

... def __init__(self, func, name=None, doc=None):

... self.__name__ = name or func.__name__

... self.__module__ = func.__module__

... self.__doc__ = doc or func.__doc__

... self.func = func

... def __get__(self, obj, type=None):

... if obj is None:

... return self

... value = obj.__dict__.get(self.__name__, _missing)

... if value is _missing:

... value = self.func(obj)

... obj.__dict__[self.__name__] = value

... return value

元類里提前定義類方法

這樣可以像定義基類一樣,提前給類定義一些方法。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17>>>class HelloMeta(type):

... def __new__(cls, name, bases, attrs):

... def __init__(cls, func):

... cls.func = func

... def hello(cls):

... print 'hello world'

... t = type.__new__(cls, name, bases, attrs)

... t.__init__ = __init__

... t.hello = hello

... return t # 最后要返回創建的類

...

>>>class Hello(object):

... __metaclass__ = HelloMeta

...

>>>h = Hello(lambda x: x+1)

>>>h.hello()

hello world

開發陷阱(一):可變的默認參數

把臨時變量作為默認參數里確實是不錯的辦法,但要警惕默認參數必須指向一個不可變類型,否則會踩到下面的坑

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16>>>def append_to(element, to=[]):

... to.append(element)

... return to

...

>>>my_list = append_to(12)

>>>my_list

[12]

>>>my_other_list = append_to(42)

>>>my_other_list

[12, 42] # 由于[]是可變類型,上次調用的元素還在里面

# 正確的做法是如下

>>>def append_to(element, to=None):

... if to is None:

... to = []

... to.append(element)

... return to

開發陷阱(二):閉包變量綁定

看懂這個坑,需要先理解閉包,推薦一篇文章;

劉志軍:一步一步教你認識Python閉包

?

下面我更換了 PPT 里的代碼,坑看得更清楚一些。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15>>>def create():

... a = []

... for i in range(4):

... def demo(x):

... return x*i

... a.append(demo)

... return a

...

>>>for demo in create():

... print demo(2)

...# 以為是 0 2 4 6 ,實際卻是:

6

6

6

6

為什么會這樣?

原因是:因為變量 i 是在閉包的作用域(demo 函數的外層作用域),而 Python 的閉包是遲綁定 ,這意味著閉包中用到的變量的值,是在內部函數被調用時查詢得到的;

也就是說,create() 生成實例時,內部的 for 循環開始,使變量 i 的最終變成了 3,當隨后循環調用閉包 demo(2) 時,在內部調用的 i 實際都是 3,要解決這個問題,可以如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17>>>def create():

... a = []

... for i in range(4):

... def demo(x, i=i): # 把i綁定成demo的參數

... return x*i

... a.append(demo)

... return a

...

>>># 或者這樣:

>>>from functools import partial

>>>from operator import mul

>>>def create_multipliers():

... return [partial(mul, i) for i in range(5)]

...

>>># 另外我發現也可以改成生成器表達式:

>>>def create_multipliers():

... return (lambda x : i * x for i in range(4))

中間還有一些其他內建模塊的用法,廖雪峰的教程里都有,就不贅述

總結

以上是生活随笔為你收集整理的python入门必备10个坑_适合 Python 初学者的一些技巧和坑的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。