溫故而知新--day1

溫故而知新--day1

變量類型

變量是計算機存儲數據的內存空間,因爲計算機能夠處理不一樣的數據,不一樣的數據就要定義不一樣的數據類型。python的數據類型不少,還能夠自定義數據類型,經常使用的通常數據類型有如下幾種:html

  1. 整型:
    • 在python2版本中有long和int之分,但到了python3中就只有int了。
    • 除此以外,整型還有進制的概念:二進制:0b10表示十進制2,八進制:0o10表示十進制8,十進制:10,十六進制:0x10表示十進制16
  2. 浮點型:
    • 即float,也就是小數,稱之爲浮點型是由於按照科學記數法表示時,一個浮點數的小數點位置是可變的。
  3. 字符串
    • "'括起來的字符,好比:"hello, world"。
    • 在表示多行字符串時,可使用三個單引號(''')/雙引號(""")括起來
  4. 布爾型
    • 表示的是真或假,一般使用True或False表示。
    • 一些表達式的結果也能夠表示真假,如:1 != 2
    • 空的數據類型(""、[]、{})和None0表示False,反之爲True
  5. 複數
    • 如3+5j,跟數學上的複數表示同樣,惟一不一樣的是虛部的i換成了j,瞭解便可。

函數

基本概念

計算機的函數實質上就是一段有特定功能的代碼,使用函數能夠有效的減小代碼的耦合度,同時提升代碼的可讀性和易維護性。python

函數的寫法

計算機的函數和數學的函數有必定的類似性:git

  1. 有參數,至關於數學函數的自變量
  2. 有返回值,至關於數學函數的因變量

python 的函數使用def關鍵詞定義,須要寫上函數名稱,而參數值和返回值須要根據需求考慮是否填寫。
如:github

def foo(num):
	return num + 1

參數

前面說過,參數就至關於數學函數的自變量,主要是一些在函數體中用到的值,python的參數能夠指定默認的參數。markdown

def pow(num, count=2):
	"""計算多少次方"""
	return num ** count
	
if __name__ == "__main__":
	print(pow(2))		# 4
	print(pow(2, 3))	# 8

上面的函數的count參數即指定了默認參數count=2,對於某些對於參數不肯定的函數還可使用不定長參數,其方式通常爲*args**kwargs,這兩個參數接收的值的類型分別爲listdict數據結構

def foo(*args, **kwargs):
    for a in args:
        print(a)
    for k, v in kwargs.items():
        print(k, v)


if __name__ == "__main__":
    foo(1, 2, 3, **{"a": 4, "b": 5, "c": 6}, d=7)

須要注意的是:在傳入參數時,能夠根據函數參數的位置傳參,也能夠根據根據參數的關鍵字傳參。兩者能夠結合使用,但位置參數必定要在關鍵字參數以前。
好比對於def foo(a, b, c)來講,既能夠foo(1, 2, 3)也能夠foo(b=2, a=1, c=3)還能夠foo(1, c=3, b=2)但不能foo(c=3, 1, 2)app

返回值

使用返回值須要用到一個關鍵詞return,一個函數的返回值能夠是一個或多個值,也能夠是一個函數。dom

導入模塊

因爲python沒有函數重載的概念,因此假如定義了相同函數名的函數時,前一個函數會被後一個函數所覆蓋:python2.7

def foo():
	print("foo1")

def foo():
	print("foo2")

在平常的開發過程當中,假如是一我的開發的話能夠爲不一樣的函數取不一樣的名字,但假如是多人開發的話就有可能使用相同的函數名。多人開發時一般使用模塊(module)開發,在使用時可使用import關鍵字導入某個指定的模塊。
m1.py:函數

def foo():
	print("foo1")

m2.py:

def foo():
	print("foo2")

在使用時:

import m1
import m2

# 使用
m1.foo()
m2.foo()

須要注意的是:導入模塊時會將模塊的內容執行一遍,假如不想這樣的話,可使用一個判斷語句,使代碼主動執行時運行,而不是導入時也運行。

def foo():
	print("foo")
	
if __name__ == "___main__":
	foo()

__name__是Python中一個隱含的變量它表明了模塊的名字,只有被Python解釋器直接執行的模塊的名字纔是__main__。

做用域

做用域就至關於一個變量可使用的範圍,該做用域的變量只能本做用域和子做用域可用。有了做用域這個概念就有了全局變量和局部變量這二者變量,全局變量即聲明在全局做用域中的變量,而局部變量則不是聲明在全局的變量,通常來講是一些函數內部聲明的變量。

n = 2	# 全局變量

def foo():
	m = 3	# 局部變量

根據python的規則,變量會優先找本做用域的,假如找不到會依次往外找,直至找到,當找不到時就會報錯。

age = 19
def main():
	print(age)
	
main()

但假如要修改外部做用域的變量時,必須使用globalnonlocal這兩個關鍵字聲明一下,不然報錯。由於python會認爲修改的這個動做實際上是聲明,也就是說python沒有朝外找變量,假如使用變量在聲明變量以前的話,就會報錯:UnboundLocalError: local variable 'xxx' referenced before assignment

# 這是錯誤的示範
age = 18

def main():
    print(age)
    age = 20


main()
print(age)

正確的方法:

  1. global
age = 18

def main():
    global age
    print(age)
    age = 20

main()
print(age)

若是咱們但願函數內部的函數可以修改嵌套做用域中的變量,可使用nonlocal關鍵字來指示變量來自於嵌套做用域。
2. nonlocal

def test1():
    count = 0
    def test2():
        nonlocal count
        count += 1
        return count
    return test2()
 
print(test1())

練習

  1. 實現計算求最大公約數和最小公倍數的函數。

    幾個整數中公有的約數,叫作這幾個數的公約數;其中最大的一個,叫作這幾個數的最大公約數。例如:十二、16的公約數有一、二、4,其中最大的一個是4,4是12與16的最大公約數。

  2. 實現判斷一個數是否是素數的函數

# 第一題 求最大公約數和最小公倍數
def gcd(x, y):
    """最大公約數"""
    (x, y) = (y, x) if x > y else (x, y)
    for i in range(x, 0, -1):
        if x % i == 0 and y % i == 0:
            return i


def lcm(x, y):
    """最小公倍數"""
    return x * y // gcd(x, y)


# 第二題
def is_prime(num):
    """判斷一個數是否是素數"""
    for factor in range(2, int(num ** 0.5) + 1):
        if num % factor == 0:
            return False
    return True if num != 1 else False

經常使用數據結構

字符串 str

字符串實質上就是由字符組成的有序序列。前面說過字符串是以引號括起來的,引號裏面的內容可使用\進行轉義,使通常的字符特殊化,如:"\n"表示換行,"\\"表示反斜槓\,除此以外轉義符還能夠跟八進制(\141)、十六進制(\x61)和Unicode編碼。
一些經常使用的轉義符

字符 含義
\ 在行尾時是續行符
\\ 反斜槓符號
\' 單引號
\" 雙引號
\a 響鈴
\b 退格
\e 轉義
\000  空 
\n 換行
\v   縱向製表符
\t 橫向製表符
\r 回車
\f 換頁

除了轉義之外,字符串還有不少使用方法。

  1. 切片
s = "hello, world"

print(s[1:4])

如上所述,切片實質上就是拿中括號寫成[開頭:結尾:步長]的形式(步長能夠省略,且默認爲一),把須要截取的一部份內容取出來,不過須要注意的是:切片裏面的數不能超過要切片的範圍,python的索引以0開始。假如要取開頭([:n])或結尾([n:])的話,能夠空着。

  1. 其餘方法
    python的字符串還有不少的其餘方法,這些方法本質上就是一些函數,使用時以"".xxx()的形式調用。
s = "hello world"

# 大寫
print(s.upper())    # HELLO WORLD

# 首字母大寫
print(s.title())    # Hello World

# 小寫
print(s.lower())    # hello world

# 替換
print(s.replace("world", "world!"))  # hello world!

# 分割
print(s.split(" "))  # ['hello', 'world']

# join
print(" ".join(["hello", "world"]))  # hello world

# 兩邊去空
print(" hello world ".strip())    # hello world

# 查找
# 找的是第一個的位置,用rfind能夠找最後一個
print(s.find("l"))      # 2
# print(s.index("t")) # 找不着時會報錯

# 判斷開頭、結尾
print(s.startswith("hello"))    # True
print(s.endswith("ld"))         # True

列表 list

列表也是python的一種經常使用的數據結構,上面例子中split方法的結果就是一個列表。列表由一個個元素組成,各個元素的類型能夠各不相同,與字符同樣,列表能夠切片、也有一些特定的方法,不同的是,列表能夠直接經過索引對元素進行修改,而字符串則不能夠。

fruits_list = ["apple", "pear", "peach", "banana"]

print(fruits_list[1:])  # ['pear', 'peach', 'banana']

# 修改值
fruits_list[2] = "orange"   # ['apple', 'pear', 'orange', 'banana']

# 追加
fruits_list.append("pear")  # ['apple', 'pear', 'orange', 'banana', 'pear']

# 插入
# 第一個參數是位置,第二個參數是要插入的元素

fruits_list.insert(0, "cherry")
# ['cherry', 'apple', 'pear', 'orange', 'banana', 'pear']


# 迭代添加一個列表

fruits_list.extend(["watermelon", "lemon"])
# ['cherry', 'apple', 'pear', 'orange', 'banana', 'pear', 'watermelon', 'lemon']


# 刪除
# 按索引位置刪除
fruits_list.pop(0)
# ['apple', 'pear', 'orange', 'banana', 'pear', 'watermelon', 'lemon']


# 刪列表中的第一個指定值

fruits_list.remove("pear")
# ['apple', 'orange', 'banana', 'pear', 'watermelon', 'lemon']


# 排序
# 能夠跟匿名函數lambda:fruits_list.sort(key=lambda x: len(x))

fruits_list.sort()
# ['apple', 'banana', 'lemon', 'orange', 'pear', 'watermelon']


# 查找
# 第一個指定值的位置
print(fruits_list.index("pear"))    # 4

# 清空
fruits_list.clear()  # []

元組 tuple

元組是一種相似於列表的數據結構,它以小括號()括起來爲一個元組,元組的元素一樣能夠是任意的。可是須要注意的是,元組的元素並不能被改變,這一種特性這某些場合中適用,如某些重要的數據、不容許改變的類屬性(__slots__)和函數的多返回值。因爲元組不能被修改,因此咱們只須要關注其定義和使用便可。

# 定義元組

fruits_tuple = ("apple", "pear", "peach", "banana")
# 也可使用tuple從其餘可迭代數據轉換過來
fruits_tuple = tuple(["apple", "pear", "banana", "peach", "banana"])
print(fruits_tuple)

# 遍歷
for f in fruits_tuple:
    print(f)


# 計數
print(fruits_tuple.count("banana"))     # 2

# 查找
print(fruits_tuple.index("banana"))     # 2

元組在內存上比列表更小,換句話說使用元組能夠節省內存,使用sys.getziseof函數能夠返回該對象的字節數。

import sys

print(sys.getsizeof(("apple", "pear", "peach", "banana")))  # 72
print(sys.getsizeof(["apple", "pear", "peach", "banana"]))  # 88

字典 dict

字典是由一個個鍵值對組成的數據結構,它以大括號({})括起來爲一個數據,通常的形式爲:{"key": "value}。須要注意的是,字典的鍵不能重複,也就是說,假如再次給已經存在的鍵賦值時,原來的值會被替換;並且鍵是能夠被哈希的數據,通常來講,python不可變的內置類型均可以被哈希,而列表和字典是可變的,不可被哈希,因此不能做爲集合的元素。。

data = {
    "name": "lczmx",
    "age": 18,
    "address": "xxx",
}

# 獲取

# 1. 使用中括號,相似於索引的方法,假如沒有該鍵的話會報錯
print(data["name"])                  # lczmx
# 2. 使用get方法,沒有該鍵時,返回另外一個參數
print(data.get("name", "none"))      # lczmx

# 3. 獲取鍵值對
for k, v in data.items():
    print(f"key: {k} value: {v}")

# 4. 獲取鍵或值
for k in data.keys():
    print(f"key: {k}")

for v in data.values():
    print("value: %s" % v)


# 更新
# 1. update
data.update({"score": 99, "student": True})				# 寫法一
data.update(score=99, student=True)						# 寫法二
# {'name': 'lczmx', 'age': 18, 'address': 'xxx', 'score': 99, 'student': True}

# 2. fromkeys
# 將一個可迭代的數據的元素做爲鍵,爲多個鍵建立統一的值
# 注意,這是dict的方法
d2 = dict.fromkeys(["a", "b", "c"], "123")
print(d2)               # {'a': '123', 'b': '123', 'c': '123'}

# 3. setdefault
# 存在取對應的值,不存在則新增鍵值對
print(data.setdefault("name", "lczmx"))     # lczmx

# 刪除
# 1. 隨機刪除,返回被刪除的鍵值對
print(data.popitem())       # ('student', True)

# 2. 刪除鍵對應的值,不存在時返回的二個參數

print(data.pop("name", "already delete"))       # lczmx

# 3. 清空
data.clear()
print(data)		# {}

集合 set

python的集合與數學上的集合是同樣的,有交集、差集、並集、補集等操做,並且元素是惟一無序的。注意:元素的類型不可變的,準確的說:能夠被哈希的數據類型可成爲元素。根據集合的這些特性,通常來講其用途通常有兩個方面:1. 關係測試(相交等)、2. 去重。

fruits1 = {'cherry', 'pear', 'banana', 'watermelon', 'lemon'}
fruits2 = set(['apple', 'pear', 'banana', 'orange'])


# 添加
fruits2.add("lemon")

# 交差並集能夠用方法實現,也能夠用符號實現
# 交集
print(fruits1.intersection(fruits2))
print(fruits1 & fruits2)
# {'banana', 'lemon', 'pear'}


# 差集
print(fruits1.difference(fruits2))
print(fruits1 - fruits2)
# {'watermelon', 'cherry'}

# 並集

print(fruits1.union(fruits2))
print(fruits1 | fruits2)

# {'banana', 'orange', 'pear', 'cherry', 'watermelon', 'lemon', 'apple'}


# 刪除
# 1. remove
# 刪除指定元素,不存在則報錯
fruits1.remove("banana")

# 2. discard
# 刪除指定元素,不存在不報錯
fruits1.discard("apple")

假如定義的時候用forzenset定義的話,則該集合不可變。

推導式

推導式是一種構建數據的快捷方式,假如用得好能夠簡化代碼,提升可讀性。但假如濫用推導式,就有可能下降代碼可讀性。通常來講,超過兩個for循環的代碼,就不適合用推導式了,而直接用多個循環寫了。

列表推導式

顧名思義,即生成列表的推導式,和定義列表同樣,列表推導式用中括號包裹着表達式。
假若有這樣一個需求:
num = [18, 22, 23, 50]裏面的數加一,咱們當然能夠,使用一個for循環把每一個元素加一,而後放回原來的列表中。但使用列表推到式只須要一行代碼便可:num = [n + 1 for n in num]
上面的例子只有一個循環,但假如多個循環該怎麼作,若是如今有num和code兩個列表:

num = [1, 2, 3, 4, 5]
code = ["A", "B", "C", "D"]

要求他們相互組合成['A1', 'A2', 'A3', 'A4', 'A5', 'B1', 'B2', 'B3', 'B4', 'B5', 'C1', 'C2', 'C3', 'C4', 'C5', 'D1', 'D2', 'D3', 'D4', 'D5']
很簡單:

num = [1, 2, 3, 4, 5]
code = ["A", "B", "C", "D"]


result = [c + str(n) for c in code for n in num]
print(result)

python2.7的版本中使用列表推導式有可能有變量泄露的風險,但在python3中則沒有該顧慮,能夠放心使用。

生成器表達式

雖然可使用列表推導式初始化元組等其它序列類型,可是生成器表達式是更好的選擇。因爲生成器遵循迭代器協議,能夠在用到時才生成元素,能夠減小內存開銷。生成器表達式在書寫上與列表推導式僅僅是把中括號換成了小括號。
好比一樣是上面的那個例子:

import sys


num = [1, 2, 3, 4, 5]
code = ["A", "B", "C", "D"]


result_list = [c + str(n) for c in code for n in num]
result_tuple = tuple([c + str(n) for c in code for n in num])
result_gen = (c + str(n) for c in code for n in num)

print(sys.getsizeof(result_list), sys.getsizeof(
    result_tuple), sys.getsizeof(result_gen))
# 256 200 112

使用生成器除了能夠用生成器表達式,也能夠用yeild關鍵字:

def gen_result():
    num = [1, 2, 3, 4, 5]
    code = ["A", "B", "C", "D"]
    for c in code:
        for n in num:
            yield c + str(n)


for i in gen_result():
    print(i)

字典推導式

自python2.7以來,列表推導式和生成器表達式的概念就移植到了字典上(集合也同樣),所以就有了字典推導式。使用字典推導式能夠將可迭代的數據做爲鍵值對構建出字典。
例子:

temp = ["A1", "B2", "C3", "D4"]

result_dict = {c: n for c, n in temp}
print(result_dict)      # {'A': '1', 'B': '2', 'C': '3', 'D': '4'}

假如是由兩個可迭代數據組成字典的話,可使用zip函數:

num = ["1", "2", "3", "4"]
code = ["A", "B", "C", "D"]


result_dict = dict(zip(code, num))
print(result_dict)      # {'A': '1', 'B': '2', 'C': '3', 'D': '4'}

集合推導式

集合推導式跟列表推導式用起來差很少,下面舉個簡單的例子便可:

num = ["1", "2", "3", "4"]
code = ["A", "B", "C", "D"]


result_set = {c + str(n) for c in code for n in num}
print(result_set)

# {'D3', 'C3', 'A2', 'D1', 'C1', 'C2', 'B4', 'B2', 'B3', 'C4', 'A1', 'D2', 'D4', 'A3', 'B1', 'A4'}

練習

  1. 在屏幕上顯示跑馬燈文字。
import time


def main():
    string = "放飛你的青春,奔灑你的熱情。 "
    while True:
        print("\r%s" % string, end="")
        string = string[1:] + string[0]	# 把第一個字符放到最後一個,以達到運動的效果
        time.sleep(0.2)


if __name__ == '__main__':
    main()
  1. 設計一個函數產生指定長度的驗證碼,驗證碼由大小寫字母和數字構成。
import random


def veri_code(count=4):
    chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
    temp = ""
    for _ in range(count):
        temp += random.sample(chars, 1)[0]
    return temp


def main():
    print(veri_code())


if __name__ == '__main__':
    main()
  1. 設計一個函數返回給定文件名的後綴名。
def get_suffix(filename):
    if "." in filename:
        return filename.split(".")[-1]
    else:
        return ""
  1. 設計一個函數返回傳入的列表中最大和第二大的元素的值。
def get_max(data: list):
    max1 = 0    # 最大
    max2 = 0    # 第二大
    for d in data:
        if d > max1:
            max2 = max1
            max1 = d
        else:
            if d > max2:
                max2 = d
    return max1, max2
  1. 打印楊輝三角。
def triangles():
    L = [1]
    while True:
        yield L
        L = [sum(i) for i in zip([0] + L, L + [0])]		# zip和sum結合,不過要在兩邊加0

個人github
個人博客
個人筆記

相關文章
相關標籤/搜索