python 基礎雜談(一)

目錄

運算符

成員運算符

身份運算符

模塊和包         

常用高階函數

lambda函數

filter函數

map函數

reduce函數

類的屬性和方法

繼承 

多態

類的高級屬性

類變量 VS 實例變量

實例方法

類方法

靜態方法


 

運算符

成員運算符

in :指定序列中找到值返回True,否則返回False

not in:指定序列中沒有找到值返回True,否則返回False

身份運算符

is:判斷兩個變量是否引用自同一個對象

is not:判斷兩個變量是否引用自同一個對象。

身份運算符 VS 比較運算符(==)

  1. ==:數值比較,is 內存地址比較
    a, b= "sunny" * 10, "sunny" * 10
    print("a == b : {}".format(a == b))
    print("a is b : {}".format(a is b))
    a = b
    print("a == b : {}".format(a == b))
    print("a is b : {}".format(a is b))

    a, b = [1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6]
    print("a == b : {}".format(a == b))
    print("a is b : {}".format(a is b))
    a = b
    print("a == b : {}".format(a == b))
    print("a is b : {}".format(a is b))
    

  2. 在python中,在一定的範圍內,值相同的數字和字符串共用相同的內存地址。對象屬於小數據池中的數據,當對象被銷燬,python只會將這個對象引用回收掉,然而內存數據還是存在的,當由其他對象引用到該值時,會發現新的對象的內存地址跟之前銷燬的內存地址是一樣的。
    a, b, c = 5, 5, 5.0
    print("a == b : {}".format(a == b))
    print("a is b : {}".format(a is b))
    print("a == c : {}".format(a == c))
    print("a is c : {}".format(a is c))
    a = c
    print("a == c : {}".format(a == c))
    print("a is c : {}".format(a is c))
    print("=" * 10)

  3. a, b = 500000000000, 500000000000
    print("a == b : {}".format(a == b))
    print("a is b : {}".format(a is b))

  4. a, b= "sunny", "sunny"
    print("a == b : {}".format(a == b))
    print("a is b : {}".format(a is b))

模塊和包         

模塊就是程序,模塊的名稱就是不含.py後綴的文件名。

模塊屬性:

  • dir-列出對象的所有屬性即方法
  • help-查看類,方法的幫助信息
  • __name__-模塊的名稱,直接運行該模塊其名是__main__,在其他地方調用該模塊,其名是模塊的名稱(這也是爲啥在模塊測試的時候,可以用if __name__ == "__main__",這樣可保證在調用的時候if裏的語句不運行,只有在直接運行的時候才運行)
  • __file__-模塊的全路徑

包的簡介

  • 可以用來組織模塊(可以包含其他模塊的模塊)
  • 目錄必須包含文件__init__.py
  • 解決模塊重名問題

__init__.py

  • 將一個文件夾變爲一個包
  • 導入包實際上是導入它的__init__.py
  • 一般爲空,可以批量導入所需的模塊

存在相對路徑導入的模塊,是不能直接運行的。

指定別名:可以解決導入後的重名問題;也可以方便書寫,例如import as np;*不支持指定別名

可以全局導入也可以局部導入。

第一次導入包會運行包下__init__.py的代碼,第一次導入包下的模塊,會先運行包下__init__.py中的代碼(若該包及其下的模塊沒有被導入過),再運行該模塊的代碼(若該模塊之前未被間接導入過)。當然只有第一次導入會運行,後面就不會再運行了。

__init__.py

print("start package test_package")
from . import a
print("end package test_package")

a.py

print("start a")
def s(a, b):
    return a + b
print(s(1, 2))
print("end a")

b.py

from . import a
print("test_package b")

test.py

import test_package.b

可以看出,調用test_package下的模塊b,會先運行test_package下__init__.py的代碼(由於__init__.py導入了a,會執行a中代碼),再執行b中代碼(雖然b中也導入了a,但是a已經在__init__.py文件中導入過了,這邊不再執行)。

test.py

from test_package.a import s
import test_package.b

常用高階函數

lambda函數

是一種表達式,創建內嵌的簡單匿名函數

filter函數

用於對序列過濾,返回一個filter對象,其中包含對其執行函數時結果爲真的所有元素。

filter(func, seq)#傳入的函數可以是lambda函數,也可以是自定義函數。

def f(n):
    return n % 2 != 0

l = list(range(1, 10))
print("原始列表:    {}".format(l))
print("filter+函數,轉換成列表: {}".format(list(filter(f, l))))

lf = filter(lambda n: n % 2 != 0, l)
print("filter+lambda函數,返回filter對象:    {}".format(lf))
print("filter+lambda函數,轉換成列表:    {}".format(list(lf)))

map函數

創建一個列表,其中包含對指定序列包含的項執行指定函數返回的值。
map(func,sequence,...) #傳入的可以是序列也可以是元組以及列表

def pow_number(l):
    res = []
    for x in l:
        res.append(x * x)
    return res

def f(n):
    return n * n

l = list(range(10))
print("函數調用:    {}".format(pow_number(l)))  # 函數調用
print("列表生成式:   {}".format([x * x for x in l]))  # 列表生成式
print("map+lambda函數,返回map對象:    {}".format(map(lambda n: n * n, l)))  # map+lambda函數
print("map+lambda函數:    {}".format(list(map(lambda n: n * n, l))))  # map+lambda函數
print("map+函數調用:    {}".format(list(map(f, l))))  # map + 函數調用

reduce函數

使用指定的函數將序列的前兩個元素合二爲一,再將結果與第三個元素合二爲一,依次類推,直到處理完整個序列並得到的一個結果。 reduce(func, seq[, initial]) 等價於 func(func(func(seq[0],seq[1]), seq[2]), ...)。

from functools import reduce

def f(a, b):
    return a + b

l = list(range(10))
print("reduce+函數調用: {}".format(reduce(f, l)))
print("reduce+lambda函數: {}".format(reduce(lambda a, b: a + b, l)))

類的屬性和方法

類名建議首字母大寫,通常用駝峯規則命名。變量名建議小寫,下劃線隔開。類最基本的作用是封裝。

構造函數:自動執行,可以不寫return,此時返回類型是None,不能強制返回其他類型

self代表當前類的實例對象,self.name表示將name綁定到實例上,即該類有實例屬性name,等號右邊的name表示__init__()中的參數name。在訪問該屬性時可以使用創建的實例對象調用。tag是類屬性。

class Cat(object):
    # 類屬性
    tag = "Cat"
    
    def __init__(self, name):
        # 實例屬性
        self.name = name

繼承 

  • 一種類與類之間的關係
  • 使用已存在的類的定義作爲基礎建立新類
  • 新類的定義可以增加新的數據或新的功能,也可以用父類的功能,但不能選擇性地繼承父類
  • 繼承的關係: · 滿足“A is B ”的關係就可以形成繼承關係

一個對象是否是某個類的實例:issubclass(對象, 類),判斷對象是否是類的實例,具有傳遞性。即若類是對象所屬類的直接父類或間接父類均返回True

一個類是否是另一個類的子類:isinstance(類1, 類2),判斷類1是否是類2 的子類,具有傳遞性。即若2是1的直接父類或間接父類均返回True

class Cat(object):
    # 類屬性
    tag = "Cat"

    def __init__(self, name="o"):
        # 實例屬性
        self.name = name


class PetCat(Cat):
    pass


pet_cat = PetCat()

print("PetCat 是 object 的子類: {}".format(issubclass(PetCat, object)))
print("pet_cat 是 Cat 的子類: {}".format(isinstance(pet_cat, Cat)))

  

類的多重繼承 能不用就不用,用的話要用清晰 一個類有多個父類,就是多重繼承 多重繼承時,如果有重名的方法,只會調用第一個。

class CoutryProtectedMixin(object):
    def show(self):
        print("protected by country")


class ProtectedMixin(object):
    def show(self):
        print("protected by province")


class Cat(ProtectedMixin, CoutryProtectedMixin):
    pass


cat = Cat()
cat.show()

多態

  • 定義:意味着允許不同類的對象對同一消息作出不同的響應
  • 必要條件:
    • 滿足繼承關係
    • 父類引用指向子類對象(必須有方法的重寫)
class Cat(object):
    def __init__(self, name):
        self.name = name
        print("Cat init")

    def show(self):
        print("name: {}".format(self.name))


class PetCat(Cat):
    def __init__(self, name, color):
        super().__init__(name)
        self.color = color
        print("PetCat init")

    def show(self):
        print("name: {}, color: {}".format(self.name, self.color))


cat = Cat("huanghuang")
cat.show()
print("=" * 10)
pet_cat = PetCat("huahua", "blue")
pet_cat.show()

類的高級屬性

@property:將類的方法當做屬性來使用,使用時寫在方法的前面,且調用被修飾的方法時,只能當屬性調用,即不加(),否則執行完方法體後會拋出異常,同時使用@property來修飾的方法不能帶參數

@方法名.setter 當屬性設置爲私有屬性時,在外部不可以直接修改,因此可以同時使用@property 和 @方法名.setter 從而可以修改私有屬性的值 可以理解爲@property表示只讀,@property 和@方法名.setter表示可讀可寫 setter裝飾器必須在property的後面,且兩個被修飾的屬性(函數)名稱必須保持一致。

class Cat(object):
    def __init__(self, age):
        self.__age = age

    @property
    def age(self):
        return self.__age

    @age.setter
    def age(self, age):
        self.__age = age


cat = Cat(8)
rest = cat.age
print("我{}歲了".format(rest))
cat.age = 10
rest = cat.age
print("我{}歲了".format(rest))

__slots__:爲指定的類設置一個靜態的列表,爲屬性很少的類節約空間,__slots__方法用元組定義允許綁定的屬性名稱和方法名而不是列表,使用後不允許爲實例添加新的屬性或方法,但是__slots__只對本類(即父類有效),並不影響子類,即子類依舊可以添加新的屬性,當子類中也定義__slots___時,子類的靜態列表拼上父類的靜態列表就是允許子類實例化使用的屬性。

__slots__只對本類(即父類有效),並不影響子類,即子類依舊可以添加新的屬性

類變量 VS 實例變量

實例方法

      實例方法關聯的是對象,實例方法通常用來操作實例變量,定義實例方法形參要多寫一個self(也可以是別的,建議self),在傳參數時不需要給self傳值,self代表的是調用它的對象。

       在實例方法中訪問實例變量,用self.變量名訪問;訪問類變量,用類名.變量名,或者self.__class__.變量名。

       在類的外部訪問實例變量,可以用對象名.變量名;在類的外部訪問類變量,可以用類名.變量名。

類方法

       類方法關聯的是類,類方法通常用來操作類變量,定義加@classmothod,形參要多寫一個cls(也可以是別的,建議cls),cls代表的是調用的類,類方法不會被自動調用

       在類方法中訪問類變量,用cls.變量名訪問;可以用類也可以用對象調用類方法(但是不建議用對象調用類方法,畢竟邏輯不符),在類方法中不可以訪問實例變量。

靜態方法

       靜態方法定義加@staticmethod,不強制多傳一個形參。可以用類也可以用對象調用靜態方法,靜態方法也可以訪問類變量,和類方法沒啥太多區別,在靜態方法中不可以訪問實例變量。不推薦用靜態方法,因爲靜態方法不是很能體現面向對象的特點。

通過在方法名前加__將方法變爲私有的,在外部不可以通過對象名/類名.__方法名訪問。python在類外部可以通過對象名.變量名添加實例變量。嚴格來講python並沒有真正的私有變量,因爲可以通過對象名._類名__變量名。

 

繼承:

       調用父類的方法可以通過super。

https://pan.baidu.com/s/1ebpbzN6YLnUzCGxO9V-MGg

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章