最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python中一些深不見底的“坑”

 更新時間:2019年06月12日 09:12:18   作者:python派森  
這篇文章主要給大家介紹了關于Python中一些深不見底的“坑”,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Python具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

Python是一門清晰簡潔的語言,如果你對一些細節(jié)不了解的話,就會掉入到那些深不見底的“坑”里,下面,我就來總結一些Python里常見的坑。

列表創(chuàng)建和引用

嵌套列表的創(chuàng)建

使用*號來創(chuàng)建一個嵌套的list:

  li = [[]] * 3
  print(li)
  # Out: [[], [], []]

通過這個方法,可以得到一個包含3個list的嵌套list,我們來給第一個list增加一個元素:

  li[0].append(1)
  print(li)
  # Out: [[1], [1], [1]]

通過輸出的結果可以看初,我們只給第一元素增加元素,結果三個list都增加了一個元素。這是因為[[]]*3并不是創(chuàng)建了三個不同list,而是創(chuàng)建了三個指向同一個list的對象,所以,當我們操作第一個元素時,其他兩個元素內容也會發(fā)生變化的原因。效果等同于下面這段代碼:

  li = []
  element = [[]]
  li = element + element + element
  print(li)
  # Out: [[], [], []]
  element.append(1)
  print(li)
  # Out: [[1], [1], [1]]

我們可以打印出元素的內存地址一探究竟:

  li = [[]] * 3
  print([id(inner_list) for inner_list in li])
  # Out: [6830760, 6830760, 6830760]

到這我們可以明白原因了。那如何解決了?可以這樣:

li = [[] for _ in range(3)]

這樣我們就創(chuàng)建了三個不同的list對象

  print([id(inner_list) for inner_list in li])
  # Out: [6331048, 6331528, 6331488]

列表元素的引用

不要使用索引方法遍歷list,例如:

  for i in range(len(tab)):
    print(tab[i])

比較好的方法是:

  for elem in tab:
  print(elem)

for語句會自動生成一個迭代器。如果你需要索引位置和元素,使用enumerate函數(shù):

  for i, elem in enumerate(tab):
    print((i, elem))

注意 == 符號的使用

  if (var == True):
    # 當var是:True、1、 1.0、 1L時if條件成立
  if (var != True):
    # 當var不是 True 和 1 時if條件成立
  if (var == False):
    # 當var是 False 或者 0 (or 0.0, 0L, 0j) if條件成立

  if (var == None):
    # var是None if條件成立

  if var:
    # 當var非空(None或者大小為0)對象 string/list/dictionary/tuple, non-0等if條件成立

  if not var:
    # 當var空(None或者大小為0)對象 string/list/dictionary/tuple, non-0等if條件成立

  if var is True:
    # 只有當var時True時 if條件成立 1也不行

  if var is False:
    # 只有當var時False時 if條件成立 0也不行

  if var is None:
  # 和var == None 一致

捕獲異常由于提前檢查

不夠優(yōu)雅的代碼:

  if os.path.isfile(file_path):
    file = open(file_path)
  else:
    # do something

比較好的做法:

  try:
    file = open(file_path)
  except OSError as e:
    # do something

在python2.6+的里面可以更簡潔:

with open(file_path) as file:

之所以這么用,是這么寫更加通用,比如file_path給你傳個None就瞎了,還得判斷是不是None,如果不判斷,就又得抓異常,判斷的話,代碼有多寫了很多。

類變量初始化

不要在對象的init函數(shù)之外初始化類屬性,主要有兩個問題

  • 如果類屬性更改,則初始值更改。
  • 如果將可變對象設置為默認值,您將獲得跨實例共享的相同對象。

錯誤示范(除非你想要靜態(tài)變量)

```
  class Car(object):
    color = "red"
    wheels = [Wheel(), Wheel(), Wheel(), Wheel()]
```

正確的做法:

```
  class Car(object):
    def __init__(self):
      self.color = "red"
      self.wheels = [Wheel(), Wheel(), Wheel(), Wheel()]
```

**函數(shù)默認參數(shù)**

```
def foo(li=[]):
  li.append(1)
  print(li)

foo([2])
# Out: [2, 1]
foo([3])
# Out: [3, 1]
```

該代碼的行為與預期的一樣,但如果我們不傳遞參數(shù)呢?

```
foo()
# Out: [1] As expected...

foo()
# Out: [1, 1] Not as expected...
```

這是因為函數(shù)參數(shù)類型是定義是確認的而不是運行時,所以在兩次函數(shù)調用時,li指向的是同一個list對象,如果要解決這個問題,可以這樣:

```
def foo(li=None):
  if not li:
    li = []
  li.append(1)
  print(li)

foo()
# Out: [1]

foo()
# Out: [1]
```

這雖然解決了上述的問題,但,其他的一些對象,比如零長度的字符串,輸出的結果就不是我們想要的。

```
x = []
foo(li=x)
# Out: [1]

foo(li="")
# Out: [1]

foo(li=0) 
# Out: [1]
```

最常用的辦法是檢查參數(shù)是不是None

```
def foo(li=None):
  if li is None:
    li = []
  li.append(1)
  print(li)

foo()
# Out: [1]
```

**在遍歷時修改**

for語句在遍歷對象是會生成一個迭代器,如果你在遍歷的過程中修改對象,會產生意想不到的結果:

  alist = [0, 1, 2]
  for index, value in enumerate(alist):
    alist.pop(index)
  print(alist)
  # Out: [1]

第二個元素沒有被刪除,因為迭代按順序遍歷索引。上述循環(huán)遍歷兩次,結果如下:

  # Iteration #1
  index = 0
  alist = [0, 1, 2]
  alist.pop(0) # removes '0'

  # Iteration #2
  index = 1
  alist = [1, 2]
  alist.pop(1) # removes '2'

  # loop terminates, but alist is not empty:
  alist = [1]

如果避免這個問題了,可以創(chuàng)建另外一個list

  alist = [1,2,3,4,5,6,7]
  for index, item in reversed(list(enumerate(alist))):
    # delete all even items
    if item % 2 == 0:
      alist.pop(index)
  print(alist)
  # Out: [1, 3, 5, 7]

整數(shù)和字符串定義

python預先緩存了一個區(qū)間的整數(shù)用來減少內存的操作,但也正是如此,有時候會出很奇特的錯誤,例如:

  >>> -8 is (-7 - 1)
  False
  >>> -3 is (-2 - 1)
  True

另外一個例子

  >>> (255 + 1) is (255 + 1)
  True
  >>> (256 + 1) is (256 + 1)
  False

通過不斷的測試,會發(fā)現(xiàn)(-3,256)這區(qū)間的整數(shù)都返回True,有的甚至是(-8,257)。默認情況下,[-5,256]會在解釋器第一次啟動時創(chuàng)建并緩存,所以才會有上面的奇怪的行為。這是個很常見但很容易被忽略的一個坑。解決方案是始終使用equality(==)運算符而不是 identity(is)運算符比較值。

Python還保留對常用字符串的引用,并且可以在比較is字符串的身份(即使用)時產生類似的混淆行為。

>>> 'python' is 'py' + 'thon'
True  

python字符串被緩存了,所有python字符串都是該對象的引用,對于不常見的字符串,即使字符串相等,比較身份也會失敗。

>>> 'this is not a common string' is 'this is not' + ' a common string'
False
>>> 'this is not a common string' == 'this is not' + ' a common string'
True

所以,就像整數(shù)規(guī)則一樣,總是使用equal(==)運算符而不是 identity(is)運算符比較字符串值。
列表推導和循環(huán)中的變量泄漏

有個例子:

  i = 0
  a = [i for i in range(3)]
  print(i) # Outputs 2

python2中列表推導改變了i變量的值,而python3修復了這個問題:

  i = 0
  a = [i for i in range(3)]
  print(i) # Outputs 0

類似地,for循環(huán)對于它們的迭代變量沒有私有的作用域

  i = 0
  for i in range(3):
    pass
  print(i) # Outputs 2

這種行為發(fā)生在Python 2和Python 3中。

為了避免泄漏變量的問題,請在列表推導和for循環(huán)中使用新的變量。

or操作符

例如

if a == 3 or b == 3 or c == 3:

這個很簡單,但是,再看一個:

if a or b or c == 3: # Wrong

這是由于or的優(yōu)先級低于==,所以表達式將被評估為if (a) or (b) or (c == 3):。正確的方法是明確檢查所有條件:

if a == 3 or b == 3 or c == 3: # Right Way

或者,可以使用內置函數(shù)any()代替鏈接or運算符:

if any([a == 3, b == 3, c == 3]): # Right

或者,為了使其更有效率:

if any(x == 3 for x in (a, b, c)): # Right

更加簡短的寫法:

if 3 in (a, b, c): # Right

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。

相關文章

  • Python利用內置庫實現(xiàn)數(shù)據(jù)的加密與校驗

    Python利用內置庫實現(xiàn)數(shù)據(jù)的加密與校驗

    這篇文章主要為大家詳細介紹了如何使用Python內置庫實現(xiàn)數(shù)據(jù)的加密和校驗,為開發(fā)者提供全方位的數(shù)據(jù)安全解決方案,感興趣的小伙伴可以跟隨小編一起學習一下
    2023-12-12
  • Python之集合詳解

    Python之集合詳解

    今天小編就為大家分享一篇關于Python中的集合介紹,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2021-09-09
  • 如何使用python爬取csdn博客訪問量

    如何使用python爬取csdn博客訪問量

    這篇文章主要介紹了如何使用python爬取csdn博客訪問量的相關資料,需要的朋友可以參考下
    2016-02-02
  • Python運維開發(fā)之psutil庫的使用詳解

    Python運維開發(fā)之psutil庫的使用詳解

    這篇文章主要介紹了Python運維開發(fā)之psutil庫的使用,psutil能夠輕松實現(xiàn)獲取系統(tǒng)運行的進程和系統(tǒng)利用率。小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • python中的super如何使用

    python中的super如何使用

    這篇文章主要介紹了python中的super,python中的super,名為超類,可以簡單的理解為執(zhí)行父類的__init__函數(shù),本文就著重看下super的具體作用,需要的朋友可以參考下
    2022-03-03
  • Python高級property屬性用法實例分析

    Python高級property屬性用法實例分析

    這篇文章主要介紹了Python高級property屬性用法,結合實例形式分析了Python property屬性的功能及各種常見的使用技巧,需要的朋友可以參考下
    2019-11-11
  • 安裝ElasticSearch搜索工具并配置Python驅動的方法

    安裝ElasticSearch搜索工具并配置Python驅動的方法

    這篇文章主要介紹了安裝ElasticSearch搜索工具并配置Python驅動的方法,文中還介紹了其與Kibana數(shù)據(jù)顯示客戶端的配合使用,需要的朋友可以參考下
    2015-12-12
  • 如何通過python檢查文件是否被占用

    如何通過python檢查文件是否被占用

    這篇文章主要介紹了如何通過python檢查文件是否被占用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Python pass詳細介紹及實例代碼

    Python pass詳細介紹及實例代碼

    這篇文章主要介紹了Python pass詳細介紹及實例代碼的相關資料,需要的朋友可以參考下
    2016-11-11
  • Python?設計模式中命令模式

    Python?設計模式中命令模式

    這篇文章主要介紹了Python?設計模式中的命令模式,命令模式的目的是解耦調用操作的對象和提供實現(xiàn)的對象,下文介紹具有一定參考價值,需要的小伙伴可以參考一下
    2022-02-02

最新評論

石柱| 博罗县| 金华市| 荥经县| 洞头县| 比如县| 万全县| 平阴县| 谢通门县| 潮州市| 确山县| 万山特区| 澄城县| 乌鲁木齐市| 昭通市| 黑水县| 台南市| 天长市| 鹤庆县| 武邑县| 辉南县| 荥经县| 连平县| 徐水县| 浏阳市| 衢州市| 大竹县| 新余市| 玉环县| 玛沁县| 大悟县| 成武县| 濮阳市| 榆林市| 丁青县| 登封市| 庐江县| 广安市| 金山区| 泗水县| 英山县|