一、成員
1.1 變量
- 實(shí)例變量,屬于對(duì)象,每個(gè)對(duì)象中各自維護(hù)自己的數(shù)據(jù)。
- 類(lèi)變量,屬于類(lèi),可以被所有對(duì)象共享,一般用于給對(duì)象提供公共數(shù)據(jù)(類(lèi)似于全局變量)。
class Person(object):
country = "中國(guó)"
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
# message = "{}-{}-{}".format(Person.country, self.name, self.age)
message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
print(Person.country) # 中國(guó)
p1 = Person("華青水上",20)
print(p1.name)
print(p1.age)
print(p1.country) # 中國(guó)
p1.show() # 中國(guó)-華青水上-20
提示:當(dāng)把每個(gè)對(duì)象中都存在的相同的示例變量時(shí),可以選擇把它放在類(lèi)變量中,這樣就可以避免對(duì)象中維護(hù)多個(gè)相同數(shù)據(jù)。
易錯(cuò)點(diǎn)
class Person(object):
country = "中國(guó)"
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
print(Person.country) # 中國(guó)
p1 = Person("華青水上",20)
print(p1.name) # 華青水上
print(p1.age) # 20
print(p1.country) # 中國(guó)
p1.show() # 中國(guó)-華青水上-20
p1.name = "root" # 在對(duì)象p1中講name重置為root
p1.num = 19 # 在對(duì)象p1中新增實(shí)例變量 num=19
p1.country = "china" # 在對(duì)象p1中新增實(shí)例變量 country="china"
print(p1.country) # china
print(Person.country) # 中國(guó)
class Person(object):
country = "中國(guó)"
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
print(Person.country) # 中國(guó)
Person.country = "美國(guó)"
p1 = Person("華青水上",20)
print(p1.name) # 華青水上
print(p1.age) # 20
print(p1.country) # 美國(guó)
class Base(object):
country = "中國(guó)"
class Person(Base):
def __init__(self, name, age):
self.name = name
self.age = age
def show(self):
message = "{}-{}-{}".format(Person.country, self.name, self.age)
# message = "{}-{}-{}".format(self.country, self.name, self.age)
print(message)
# 讀
print(Base.country) # 中國(guó)
print(Person.country) # 中國(guó)
obj = Person("華青水上",19)
print(obj.country) # 中國(guó)
# 寫(xiě)
Base.country = "china"
Person.country = "泰國(guó)"
obj.country = "日本"
1.2 方法
- 綁定方法,默認(rèn)有一個(gè)self參數(shù),由對(duì)象進(jìn)行調(diào)用(此時(shí)self就等于調(diào)用方法的這個(gè)對(duì)象)【對(duì)象類(lèi)均可調(diào)用】
- 類(lèi)方法,默認(rèn)有一個(gè)cls參數(shù),用類(lèi)或?qū)ο蠖伎梢哉{(diào)用(此時(shí)cls就等于調(diào)用方法的這個(gè)類(lèi))【對(duì)象類(lèi)均可調(diào)用】
- 靜態(tài)方法,無(wú)默認(rèn)參數(shù),用類(lèi)和對(duì)象都可以調(diào)用?!緦?duì)象類(lèi)均可調(diào)用】
class Foo(object):
def __init__(self, name,age):
self.name = name
self.age = age
def f1(self):
print("綁定方法", self.name)
@classmethod
def f2(cls):
print("類(lèi)方法", cls)
@staticmethod
def f3():
print("靜態(tài)方法")
# 綁定方法(對(duì)象)
obj = Foo("武沛齊",20)
obj.f1() # Foo.f1(obj)
# 類(lèi)方法
Foo.f2() # cls就是當(dāng)前調(diào)用這個(gè)方法的類(lèi)。(類(lèi))
obj.f2() # cls就是當(dāng)前調(diào)用這個(gè)方法的對(duì)象的類(lèi)。
# 靜態(tài)方法
Foo.f3() # 類(lèi)執(zhí)行執(zhí)行方法(類(lèi))
obj.f3() # 對(duì)象執(zhí)行執(zhí)行方法
在Python中比較靈活,方法都可以通過(guò)對(duì)象和類(lèi)進(jìn)行調(diào)用;而在java、c#等語(yǔ)言中,綁定方法只能由對(duì)象調(diào)用;類(lèi)方法或靜態(tài)方法只能由類(lèi)調(diào)用。
import os
import requests
class Download(object):
def __init__(self, folder_path):
self.folder_path = folder_path
@staticmethod
def download_dou_yin():
# 下載抖音
res = requests.get('.....')
with open("xxx.mp4", mode='wb') as f:
f.write(res.content)
def download_dou_yin_2(self):
# 下載抖音
res = requests.get('.....')
path = os.path.join(self.folder_path, 'xxx.mp4')
with open(path, mode='wb') as f:
f.write(res.content)
obj = Download("video")
obj.download_dou_yin()
1.3 屬性
屬性其實(shí)是由綁定方法 + 特殊裝飾器 組合創(chuàng)造出來(lái)的,讓我們以后在調(diào)用方法時(shí)可以不加括號(hào)。
class Foo(object):
def __init__(self, name):
self.name = name
def f1(self):
return 123
@property
def f2(self):
return 123
obj = Foo("華青水上")
v1 = obj.f1()
print(v1)
v2 = obj.f2
print(v2)
class Pagination:
def __init__(self, current_page, per_page_num=10):
self.per_page_num = per_page_num
if not current_page.isdecimal():
self.current_page = 1
return
current_page = int(current_page)
if current_page 1:
self.current_page = 1
return
self.current_page = current_page
def start(self):
return (self.current_page - 1) * self.per_page_num
def end(self):
return self.current_page * self.per_page_num
user_list = ["用戶(hù)-{}".format(i) for i in range(1, 3000)]
# 分頁(yè)顯示,每頁(yè)顯示10條
while True:
page = input("請(qǐng)輸入頁(yè)碼:")
# page,當(dāng)前訪問(wèn)的頁(yè)碼
# 10,每頁(yè)顯示10條數(shù)據(jù)
# 內(nèi)部執(zhí)行Pagination類(lèi)的init方法。
pg_object = Pagination(page, 20)
page_data_list = user_list[ pg_object.start() : pg_object.end() ]
for item in page_data_list:
print(item)
class Pagination:
def __init__(self, current_page, per_page_num=10):
self.per_page_num = per_page_num
if not current_page.isdecimal():
self.current_page = 1
return
current_page = int(current_page)
if current_page 1:
self.current_page = 1
return
self.current_page = current_page
@property
def start(self):
return (self.current_page - 1) * self.per_page_num
@property
def end(self):
return self.current_page * self.per_page_num
user_list = ["用戶(hù)-{}".format(i) for i in range(1, 3000)]
# 分頁(yè)顯示,每頁(yè)顯示10條
while True:
page = input("請(qǐng)輸入頁(yè)碼:")
pg_object = Pagination(page, 20)
page_data_list = user_list[ pg_object.start : pg_object.end ]
for item in page_data_list:
print(item)
關(guān)于屬性的編寫(xiě)有兩種方式:
class C(object):
@property
def x(self):
pass
@x.setter
def x(self, value):
pass
@x.deleter
def x(self):
pass
obj = C()
obj.x
obj.x = 123
del obj.x
class C(object):
def getx(self):
pass
def setx(self, value):
pass
def delx(self):
pass
x = property(getx, setx, delx, "I'm the 'x' property.")
obj = C()
obj.x
obj.x = 123
del obj.x
注意:由于屬性和實(shí)例變量的調(diào)用方式相同,所以在編寫(xiě)時(shí)需要注意:屬性名稱(chēng) 不要 實(shí)例變量 重名。
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
@property
def func(self):
return 123
obj = Foo("華青水上", 123)
print(obj.name)
一旦重名,可能就會(huì)有報(bào)錯(cuò)。
class Foo(object):
def __init__(self, name, age):
self.name = name # 報(bào)錯(cuò),錯(cuò)認(rèn)為你想要調(diào)用 @name.setter 裝飾的方法。
self.age = age
@property
def name(self):
return "{}-{}".format(self.name, self.age)
obj = Foo("華青水上", 123)
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
@property
def name(self):
return "{}-{}".format(self.name, self.age) # 報(bào)錯(cuò),循環(huán)調(diào)用自己(直到層級(jí)太深報(bào)錯(cuò))
@name.setter
def name(self, value):
print(value)
obj = Foo("華青水上", 123)
print(obj.name)
如果真的想要在名稱(chēng)上創(chuàng)建一些關(guān)系,可以讓實(shí)例變量加上一個(gè)下劃線。
class Foo(object):
def __init__(self, name, age):
self._name = name
self.age = age
@property
def name(self):
return "{}-{}".format(self._name, self.age)
obj = Foo("華青水上", 123)
print(obj._name)
print(obj.name)
二、成員修飾符
Python中成員的修飾符就是指的是:公有、私有。
- 公有,在任何地方都可以調(diào)用這個(gè)成員。
- 私有,只有在類(lèi)的內(nèi)部才可以調(diào)用改成員(成員是以?xún)蓚€(gè)下劃線開(kāi)頭,則表示該成員為私有)。
class Foo(object):
def __init__(self, name, age):
self.__name = name
self.age = age
def get_data(self):
return self.__name
def get_age(self):
return self.age
obj = Foo("華青水上", 123)
# 公有成員
print(obj.age)
v1 = self.get_age()
print(v1)
# 私有成員
# print(obj.__name) # 錯(cuò)誤,由于是私有成員,只能在類(lèi)中進(jìn)行使用。
v2 = obj.get_data()
print(v2)
特別提醒:父類(lèi)中的私有成員,子類(lèi)無(wú)法繼承。
class Base(object):
def __data(self):
print("base.__data")
def num(self):
print("base.num")
class Foo(Base):
def func(self):
self.num()
self.__data() # # 不允許執(zhí)行父類(lèi)中的私有方法
obj = Foo()
obj.func()
class Base(object):
def __data(self):
print("base.__data")
def num(self):
print("base.num")
self.__data() # 不允許執(zhí)行父類(lèi)中的私有方法
class Foo(Base):
def func(self):
self.num()
obj = Foo()
obj.func()
按理說(shuō)私有成員是無(wú)法被外部調(diào)用,但如果用一些特殊的語(yǔ)法也可以(Flask源碼中有這種寫(xiě)法,大家寫(xiě)代碼不推薦這樣寫(xiě))。
class Foo(object):
def __init__(self):
self.__num = 123
self.age = 19
def __msg(self):
print(1234)
obj = Foo()
print(obj.age)
print(obj._Foo__num)
obj._Foo__msg()
成員是否可以作為獨(dú)立的功能暴露給外部,讓外部調(diào)用并使用。
- 可以,公有。
- 不可以,內(nèi)部其他放的一個(gè)輔助,私有。
三、對(duì)象嵌套
在基于面向?qū)ο筮M(jìn)行編程時(shí),對(duì)象之間可以存在各種各樣的關(guān)系,例如:組合、關(guān)聯(lián)、依賴(lài)等(Java中的稱(chēng)呼),用大白話來(lái)說(shuō)就是各種嵌套。
情景一:
class Student(object):
""" 學(xué)生類(lèi) """
def __init__(self, name, age):
self.name = name
self.age = age
def message(self):
data = "我是一名學(xué)生,我叫:{},我今年{}歲".format(self.name, self.age)
print(data)
s1 = Student("華青水上", 19)
s2 = Student("殊途同歸", 19)
s3 = Student("春花秋月", 19)
class Classes(object):
""" 班級(jí)類(lèi) """
def __init__(self, title):
self.title = title
self.student_list = []
def add_student(self, stu_object):
self.student_list.append(stu_object)
def add_students(self, stu_object_list):
for stu in stu_object_list:
self.add_student(stu)
def show_members(self):
for item in self.student_list:
# print(item)
item.message()
c1 = Classes("三年二班")
c1.add_student(s1)
c1.add_students([s2, s3])
print(c1.title)
print(c1.student_list)
情景二:
class Student(object):
""" 學(xué)生類(lèi) """
def __init__(self, name, age, class_object):
self.name = name
self.age = age
self.class_object = class_object
def message(self):
data = "我是一名{}班的學(xué)生,我叫:{},我今年{}歲".format(self.class_object.title, self.name, self.age)
print(data)
class Classes(object):
""" 班級(jí)類(lèi) """
def __init__(self, title):
self.title = title
c1 = Classes("Python全棧")
c2 = Classes("Linux云計(jì)算")
user_object_list = [
Student("華青水上", 19, c1),
Student("殊途同歸", 19, c1),
Student("春花秋月", 19, c2)
]
for obj in user_object_list:
print(obj.name,obj.age, obj.class_object.title)
情景三:
class Student(object):
""" 學(xué)生類(lèi) """
def __init__(self, name, age, class_object):
self.name = name
self.age = age
self.class_object = class_object
def message(self):
data = "我是一名{}班的學(xué)生,我叫:{},我今年{}歲".format(self.class_object.title, self.name, self.age)
print(data)
class Classes(object):
""" 班級(jí)類(lèi) """
def __init__(self, title, school_object):
self.title = title
self.school_object = school_object
class School(object):
""" 學(xué)校類(lèi) """
def __init__(self, name):
self.name = name
s1 = School("北京校區(qū)")
s2 = School("上海校區(qū)")
c1 = Classes("Python全棧", s1)
c2 = Classes("Linux云計(jì)算", s2)
user_object_list = [
Student("華青水上", 19, c1),
Student("殊途同歸", 19, c1),
Student("春花秋月", 19, c2)
]
for obj in user_object_list:
print(obj.name, obj.class_object.title , obj.class_object.school_object.name)
四、特殊成員
在Python的類(lèi)中存在一些特殊的方法,這些方法都是 __方法__
格式,這種方法在內(nèi)部均有特殊的含義,接下來(lái)我們來(lái)講一些常見(jiàn)的特殊成員:
class Foo(object):
def __init__(self, name):
self.name = name
obj = Foo("華青水上")
class Foo(object):
def __init__(self, name):
print("第二步:初始化對(duì)象,在空對(duì)象中創(chuàng)建數(shù)據(jù)")
self.name = name
def __new__(cls, *args, **kwargs):
print("第一步:先創(chuàng)建空對(duì)象并返回")
return object.__new__(cls)
obj = Foo("華青水上")
class Foo(object):
def __call__(self, *args, **kwargs):
print("執(zhí)行call方法")
obj = Foo()
obj()
class Foo(object):
def __str__(self):
return "哈哈哈哈"
obj = Foo()
data = str(obj)
print(data)
class Foo(object):
def __init__(self, name, age):
self.name = name
self.age = age
obj = Foo("華青水上",19)
print(obj.__dict__)
__getitem__
、__setitem__
、__delitem__
class Foo(object):
def __getitem__(self, item):
pass
def __setitem__(self, key, value):
pass
def __delitem__(self, key):
pass
obj = Foo("華青水上", 19)
obj["x1"]
obj['x2'] = 123
del obj['x3']
class Foo(object):
def __enter__(self):
print("進(jìn)入了")
return 666
def __exit__(self, exc_type, exc_val, exc_tb):
print("出去了")
obj = Foo()
with obj as data:
print(data)
# 面試題(補(bǔ)充代碼,實(shí)現(xiàn)如下功能)
class Context:
def __enter__(self):
return self
def __exit__(self, exc_type, exc_val, exc_tb):
pass
def do_something(self): # __enter__返回self才可以調(diào)用執(zhí)行do_something方法
pass
with Context() as ctx:
ctx.do_something()
上述面試題屬于上下文管理的語(yǔ)法。
class Foo(object):
def __init__(self, name):
self.name = name
def __add__(self, other):
return "{}-{}".format(self.name, other.name)
v1 = Foo("alex")
v2 = Foo("sb")
# 對(duì)象+值,內(nèi)部會(huì)去執(zhí)行 對(duì)象.__add__方法,并將+后面的值當(dāng)做參數(shù)傳遞過(guò)去。
v3 = v1 + v2
print(v3)
迭代器
# 迭代器類(lèi)型的定義:
1.當(dāng)類(lèi)中定義了 __iter__ 和 __next__ 兩個(gè)方法。
2.__iter__ 方法需要返回對(duì)象本身,即:self
3. __next__ 方法,返回下一個(gè)數(shù)據(jù),如果沒(méi)有數(shù)據(jù)了,則需要拋出一個(gè)StopIteration的異常。
官方文檔:https://docs.python.org/3/library/stdtypes.html#iterator-types
# 創(chuàng)建 迭代器類(lèi)型 :
class IT(object):
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
# 根據(jù)類(lèi)實(shí)例化創(chuàng)建一個(gè)迭代器對(duì)象:
obj1 = IT()
# v1 = obj1.__next__()
# v2 = obj1.__next__()
# v3 = obj1.__next__() # 拋出異常
v1 = next(obj1) # obj1.__next__()
print(v1)
v2 = next(obj1)
print(v2)
v3 = next(obj1)
print(v3)
obj2 = IT()
for item in obj2: # 首先會(huì)執(zhí)行迭代器對(duì)象的__iter__方法并獲取返回值,一直去反復(fù)的執(zhí)行 next(對(duì)象)
print(item)
迭代器對(duì)象支持通過(guò)next取值,如果取值結(jié)束則自動(dòng)拋出StopIteration。
for循環(huán)內(nèi)部在循環(huán)時(shí),先執(zhí)行__iter__方法,獲取一個(gè)迭代器對(duì)象,然后不斷執(zhí)行的next取值(有異常StopIteration則終止循環(huán))。
生成器
# 創(chuàng)建生成器函數(shù)
def func():
yield 1
yield 2
# 創(chuàng)建生成器對(duì)象(內(nèi)部是根據(jù)生成器類(lèi)generator創(chuàng)建的對(duì)象),生成器類(lèi)的內(nèi)部也聲明了:__iter__、__next__ 方法。
obj1 = func()
v1 = next(obj1)
print(v1)
v2 = next(obj1)
print(v2)
v3 = next(obj1)
print(v3)
obj2 = func()
for item in obj2:
print(item)
如果按照迭代器的規(guī)定來(lái)看,其實(shí)生成器類(lèi)也是一種特殊的迭代器類(lèi)(生成器也是一個(gè)中特殊的迭代器)。
可迭代對(duì)象
# 如果一個(gè)類(lèi)中有__iter__方法且返回一個(gè)迭代器對(duì)象 ;則我們稱(chēng)以這個(gè)類(lèi)創(chuàng)建的對(duì)象為可迭代對(duì)象。
class Foo(object):
def __iter__(self):
return 迭代器對(duì)象(生成器對(duì)象)
obj = Foo() # obj是 可迭代對(duì)象。
# 可迭代對(duì)象是可以使用for來(lái)進(jìn)行循環(huán),在循環(huán)的內(nèi)部其實(shí)是先執(zhí)行 __iter__ 方法,獲取其迭代器對(duì)象,然后再在內(nèi)部執(zhí)行這個(gè)迭代器對(duì)象的next功能,逐步取值。
for item in obj:
pass
可迭代對(duì)象是可以使用for來(lái)進(jìn)行循環(huán),在循環(huán)的內(nèi)部其實(shí)是先執(zhí)行 __iter__ 方法,獲取其迭代器對(duì)象,然后再在內(nèi)部執(zhí)行這個(gè)迭代器對(duì)象的next功能,逐步取值。
class IT(object):
def __init__(self):
self.counter = 0
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == 3:
raise StopIteration()
return self.counter
class Foo(object):
def __iter__(self):
return IT()
obj = Foo() # 可迭代對(duì)象
for item in obj: # 循環(huán)可迭代對(duì)象時(shí),內(nèi)部先執(zhí)行obj.__iter__并獲取迭代器對(duì)象;不斷地執(zhí)行迭代器對(duì)象的next方法。
print(item)
# 基于可迭代對(duì)象迭代器實(shí)現(xiàn):自定義range
class IterRange(object):
def __init__(self, num):
self.num = num
self.counter = -1
def __iter__(self):
return self
def __next__(self):
self.counter += 1
if self.counter == self.num:
raise StopIteration()
return self.counter
class Xrange(object):
def __init__(self, max_num):
self.max_num = max_num
def __iter__(self):
return IterRange(self.max_num)
obj = Xrange(100)
for item in obj:
print(item)
class Foo(object):
def __iter__(self):
yield 1
yield 2
obj = Foo()
for item in obj:
print(item)
# 基于可迭代對(duì)象生成器 實(shí)現(xiàn):自定義range
class Xrange(object):
def __init__(self, max_num):
self.max_num = max_num
def __iter__(self):
counter = 0
while counter self.max_num:
yield counter
counter += 1
obj = Xrange(100)
for item in obj:
print(item)
常見(jiàn)的數(shù)據(jù)類(lèi)型:
from collections.abc import Iterator, Iterable
v1 = [11, 22, 33]
print( isinstance(v1, Iterator) ) # false,判斷是否是迭代器;判斷依據(jù)是__iter__ 和 __next__。
v2 = v1.__iter__()
print( isinstance(v2, Iterator) ) # True
v1 = [11, 22, 33]
print( isinstance(v1, Iterable) ) # True,判斷依據(jù)是是否有 __iter__且返回迭代器對(duì)象。
v2 = v1.__iter__()
print( isinstance(v2, Iterable) ) # True,判斷依據(jù)是是否有 __iter__且返回迭代器對(duì)象。
至此,Python進(jìn)階面向?qū)ο笾蓡T總結(jié)完畢,如有不當(dāng)之處歡迎指正。
到此這篇關(guān)于Python面向?qū)ο笾蓡T相關(guān)知識(shí)總結(jié)的文章就介紹到這了,更多相關(guān)Python成員內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- 簡(jiǎn)單談?wù)凱ython面向?qū)ο蟮南嚓P(guān)知識(shí)
- Python面向?qū)ο髮?shí)現(xiàn)方法總結(jié)
- 淺析Python面向?qū)ο缶幊?/li>
- python中什么是面向?qū)ο?/li>
- Python中關(guān)于面向?qū)ο蟾拍畹脑敿?xì)講解