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

Python面向?qū)ο蟪绦蛟O(shè)計(jì)類的多態(tài)用法詳解

 更新時(shí)間:2019年04月12日 11:49:23   作者:微信1257309054  
這篇文章主要介紹了Python面向?qū)ο蟪绦蛟O(shè)計(jì)類的多態(tài)用法,結(jié)合實(shí)例形式詳細(xì)分析了Python面向?qū)ο蟪绦蛟O(shè)計(jì)中類的多態(tài)概念、原理、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了Python面向?qū)ο蟪绦蛟O(shè)計(jì)類的多態(tài)用法。分享給大家供大家參考,具體如下:

多態(tài)

1、多態(tài)使用

一種事物的多種體現(xiàn)形式,舉例:動(dòng)物有很多種

注意: 繼承是多態(tài)的前提

函數(shù)重寫就是多態(tài)的體現(xiàn)形式

演示:重寫Animal類

第一步:先定義貓類和老鼠類,繼承自object,在其中書寫構(gòu)造方法和eat方法
第二步: 抽取Animal父類,定義屬性和eat方法,貓類與老鼠類繼承即可
第三步: 定義人類,在其中分別定義喂貓和喂老鼠的方法
第四步:使用多態(tài),將多個(gè)喂的方法提取一個(gè)。

# 測(cè)試類
from cat import Cat
from mouse import Mouse
from person import Person
'''
多態(tài): 一種事物的多種狀態(tài)
需求:人可以喂任何一種動(dòng)物
'''
#創(chuàng)建貓和老鼠的對(duì)象
tom = Cat("tom")
jerry = Mouse("jerry")
#調(diào)用各自的方法
tom.eat()
jerry.eat()
#定義了一個(gè)有name屬性和eat方法的Animal類,讓所有的動(dòng)物類都繼承自Animal.
#定義一個(gè)人類,可以喂貓和老鼠吃東西
per = Person()
#per.feedCat(tom)
#per.feedMouse(jerry)
#思考:人要喂100種動(dòng)物,難道要寫100個(gè)feed方法嗎?
#前提:tom和jerry都繼承自動(dòng)物
per.feedAnimal(tom)
per.feedAnimal(jerry)

輸出:

tom吃
jerry吃
給你食物
tom吃
給你食物
jerry吃

#animal.py文件中的動(dòng)物類
class Animal(object):
  def __init__(self, name):
    self.name = name
  def eat(self):
    print(self.name + "吃")

#cat.py文件中的貓類
class Cat(Animal):
  def __init__(self, name):
    #self.name = name
    super(Cat,self).__init__(name)

#mouse.py中的老鼠類
class Mouse(Animal):
  def __init__(self, name):
    #self.name = name
    super(Mouse,self).__init__(name)

#person.py中的人類
class Person(object):
  def feedAnimal(self, ani):
    print("給你食物")
    ani.eat()

2、對(duì)象屬性與類屬性

對(duì)象屬性和類屬性的區(qū)別:

a.定義的位置不同,類屬性是直接在類中的屬性,對(duì)象屬性是在定義在構(gòu)造方法中的屬性;

b.對(duì)象屬性使用對(duì)象訪問,類屬性使用類名訪問;

c.在內(nèi)存中出現(xiàn)的時(shí)機(jī)不同[類屬性隨著類的加載而出現(xiàn),對(duì)象屬性隨著對(duì)象的創(chuàng)建而出現(xiàn)];

d.優(yōu)先級(jí)不同,對(duì)象屬性的優(yōu)先級(jí)高于類屬性。

class Person(object):
  #1.定義位置
  #類屬性:直接定義在類中的屬性
  name = "person"
  def __init__(self, name):
    #對(duì)象屬性:定義在構(gòu)造方法中的屬性
    self.name = name
#2.訪問方式
print(Person.name)
per = Person("tom")
#對(duì)象屬性的優(yōu)先級(jí)高于類屬性
print(per.name)
#動(dòng)態(tài)的給對(duì)象添加對(duì)象屬性
per.age = 18
#只針對(duì)當(dāng)前對(duì)象生效,對(duì)于類創(chuàng)建的其他對(duì)象沒有作用
print(Person.name)
per2 = Person("lilei")
#print(per2.age) #沒有age屬性
#刪除對(duì)象中的name屬性,再調(diào)用會(huì)使用到同名的類屬性
del per.name
print(per.name)
#注意事項(xiàng):不要將對(duì)象屬性與類屬性重名,因?yàn)閷?duì)象屬性會(huì)屏蔽掉類屬性,但是當(dāng)刪除對(duì)象屬性之后,再使用就能使用到類屬性了.

輸出:

person
tom
person
person

3、動(dòng)態(tài)添加屬性和方法

正常情況下,我們定義了一個(gè)class,創(chuàng)建一個(gè)class的實(shí)例后,我們可以給該實(shí)例綁定任何的的屬性和方法,這就是動(dòng)態(tài)語言的靈活性。

python語言的特點(diǎn):靈活。

這里說的動(dòng)態(tài)添加屬性和方法主要指的是關(guān)于slots函數(shù)的使用

from types import MethodType
#定義一個(gè)空類
'''
class Person():
  pass
'''
class Person(object):
  __slots__ = ("name","age","speak","hobby")
  pass
# 動(dòng)態(tài)添加屬性[體現(xiàn)了動(dòng)態(tài)語言的特點(diǎn):靈活性]
per = Person()
per.name = "tom"
print(per.name)
#動(dòng)態(tài)添加方法
def say(self):
  print("my name is "+ self.name)
per.speak = say
per.speak(per)
#這樣實(shí)現(xiàn)不好,所以引入MethodType
def hobby(self):
  print("my hobby is running")
per.hobby = MethodType(hobby,per)
per.hobby()

輸出:

tom
my name is tom
my hobby is running

但是,給一個(gè)實(shí)例綁定的方法對(duì)另外一個(gè)實(shí)例是不起作用的。

為了給所有的實(shí)例都綁定方法,可以通過給class綁定方法

#動(dòng)態(tài)添加方法
def say(self,name):
  self.name = name
  print("my name is "+ self.name)
Person.speak = say
per2 = Person()
per2.speak('hh')

輸出:

my name is hh

給class綁定方法后,所有的實(shí)例均可調(diào)用。

4、slots

通常情況下,上面的say方法可以直接定義在class中,但動(dòng)態(tài)綁定允許我們?cè)诔绦蛟谶\(yùn)行的過程中動(dòng)態(tài)的給class添加功能,這在靜態(tài)語言中很難實(shí)現(xiàn)。

如果我們想限制實(shí)例的屬性怎么辦?

比如,只允許給Person實(shí)例添加name,age屬性,為了達(dá)到限制的目的,Python中允許在定義class的時(shí)候,定義一個(gè)特殊的變量【slots】變量,來限制該class添加的屬性

class Person(object):
  __slots__=("name","age")
#[不想無限制的任意添加屬性]
#比如,只允許給對(duì)象添加name, age屬性
#解決:定義類的時(shí)候,定義一個(gè)特殊的屬性(__slots__),可以限制動(dòng)態(tài)添加的屬性范圍
per = Person()
per.height = 170
print(per.height)

這樣做會(huì)報(bào)錯(cuò)

AttributeError: 'Person' object has no attribute 'height'

使用slots的時(shí)候需要注意,slots定義的屬性僅僅對(duì)當(dāng)前類的實(shí)例起作用,對(duì)繼承的子類是不起作用的。

除非在子類中也定義slots,這樣子類實(shí)例允許定義的屬性就是自身的slots加上父類的slots。

總結(jié):

__slots__:

語法:

__slots__ = (屬性名1,屬性名2,...)

作用:

限制類的屬性名

注意:當(dāng)子類沒有添加slots時(shí),子類繼承父類的時(shí)候,它的屬性名不受父類的影響

若子類中也添加slots,子類的限制應(yīng)該是父類的slots與子類slots的并集

5、@property

綁定屬性時(shí),如果我們直接把屬性暴露出去,雖然寫起來簡(jiǎn)單,但是沒有辦法檢查參數(shù),導(dǎo)致可以隨意的更改。

比如:

p = Person()
p.age = -1

這顯然不合常理,為了限制age的范圍,我們可以通過setAge()的方法來設(shè)置age,再通過getAge()的方法獲取age,這樣在setAge()中就可以檢查輸入的參數(shù)的合理性了。

class Person(object):
  def __init__(self, name, age):
    # 屬性直接對(duì)外暴露
    # self.age = age
    # 限制訪問
    self.__age = age
    self.__name = name
    # self.__name = name
  def getAge(self):
    return self.__age
  def setAge(self, age):
    if age < 0:
      age = 0
    self.__age = age
  # 通過@property和@age.setter改變?cè)瓉淼膅et/set方法
  # 方法名為受限制的變量去掉雙下劃線
  # 相當(dāng)于get方法
  @property
  def age(self):
    return self.__age
  # 相當(dāng)于set的方法
  @age.setter # 去掉下劃線.setter
  def age(self, age):
    if age < 0:
      age = 0
    self.__age = age
  @property
  def name(self):
    return self.__name
  @name.setter
  def name(self, name):
    self.__name = name
per = Person("lili", 18)
# 屬性直接對(duì)外暴露
# 不安全,沒有數(shù)據(jù)的過濾
# per.age = -10
# print(per.age)
# 使用限制訪問,需要自己寫set和get的方法才能訪問
# 劣勢(shì):麻煩,代碼不直觀
# 思考問題:如果我就想使用對(duì)象"."的方式訪問對(duì)象的私有屬性,怎么辦?
# per.setAge(15)
# print(per.getAge())
# property:可以讓你對(duì)受限制訪問的屬性使用"."語法
per.age = 80 # 相當(dāng)于調(diào)用setAge
print(per.age) # 相當(dāng)于調(diào)用getAge
print(per.name)

輸出:

80
lili

property

總結(jié)語法:

針對(duì)私有化的屬性添加的。

@property
  def 屬性名(self):
    return self.__屬性名

@屬性名.setter
  def 屬性名(self, 值):
    #業(yè)務(wù)邏輯處理
    self.屬性名 = 值

總結(jié):

a.裝飾器(decorator)可以給函數(shù)動(dòng)態(tài)加上功能,對(duì)于類的方法,裝飾器一樣起作用,python內(nèi)置的@property裝飾器就是負(fù)責(zé)把一個(gè)方法變成屬性調(diào)用的。
b.@property的實(shí)現(xiàn)比較復(fù)雜,我們先考慮如何使用,把一個(gè)getter方法變成屬性,只需要加上@property就可以了,此時(shí)@property本身又創(chuàng)建了另一個(gè)裝飾器@屬性setter,負(fù)責(zé)把一個(gè)setter方法變成屬性賦值.
c.@property廣泛應(yīng)用在類的定義中,可以讓調(diào)用者寫出簡(jiǎn)短的代碼,同時(shí)保證對(duì)參數(shù)進(jìn)行必要的檢查,這樣,程序運(yùn)行時(shí)就減少了出錯(cuò)的可能性。

6、運(yùn)算符重載

類可以重載加減運(yùn)算,打印,函數(shù)調(diào)用,索引等內(nèi)置運(yùn)算,運(yùn)算符重載使我們的對(duì)象的行為與內(nèi)置函數(shù)一樣,在python調(diào)用時(shí)操作符會(huì)自動(dòng)的作用于類的對(duì)象,python會(huì)自動(dòng)的搜索并調(diào)用對(duì)象中指定的方法完成操作。

1、常見運(yùn)算符重載方法

常見運(yùn)算符重載方法

方法名 重載說明 運(yùn)算符調(diào)用方式
init 構(gòu)造函數(shù) 對(duì)象創(chuàng)建: X = Class(args)
del 析構(gòu)函數(shù) X對(duì)象收回
add sub 加減運(yùn)算 X+Y, X+=Y/X-Y, X-=Y
or 運(yùn)算符| X|Y, X|=Y
str_ repr 打?。D(zhuǎn)換 print(X)、repr(X)/str(X)
call 函數(shù)調(diào)用 X(*args, **kwargs)
getattr 屬性引用 X.undefined
setattr 屬性賦值 X.any=value
delattr 屬性刪除 del X.any
getattribute 屬性獲取 X.any
getitem 索引運(yùn)算 X[key],X[i:j]
setitem 索引賦值 X[key],X[i:j]=sequence
delitem 索引和分片刪除 del X[key],del X[i:j]
len 長(zhǎng)度 len(X)
bool 布爾測(cè)試 bool(X)
lt gt le ge eq ne 特定的比較 依次為XY,X<=Y,X>=Y, X==Y,X!=Y 注釋:(lt: less than, gt: greater than, le: less equal, ge: greater equal, eq: equal, ne: not equal )
radd 右側(cè)加法 other+X
iadd 實(shí)地(增強(qiáng)的)加法 X+=Y(or else add)
iter next 迭代 I=iter(X), next()
contains 成員關(guān)系測(cè)試 item in X(X為任何可迭代對(duì)象)
index 整數(shù)值 hex(X), bin(X), oct(X)
enter exit 環(huán)境管理器 with obj as var:
get set delete 描述符屬性 X.attr, X.attr=value, del X.attr
new 創(chuàng)建 在init之前創(chuàng)建對(duì)象

# 舉例
# 數(shù)字和字符串都能相加
#print(1 + 2)
#print("1" + "2")
# 不同的類型用加法會(huì)有不同的解釋
class Person(object):
  def __init__(self, num):
    self.num = num
  # 運(yùn)算符重載
  def __add__(self, other):
    return Person(self.num + other.num)
  # 方法重寫
  def __str__(self):
    return "num = " + str(self.num)
# 如果兩個(gè)對(duì)象相加會(huì)怎樣?
# 對(duì)象相加,編譯器解釋不了,所以就要用到運(yùn)算符重載
per1 = Person(1)
per2 = Person(2)
print(per1 + per2)
# 結(jié)果為地址:per1+per2 === per1.__add__(per2),如果想得到num的和則重寫str方法
# 上述打印就等價(jià)于:print(per1.__add__(per2)),只不過add方法會(huì)自動(dòng)調(diào)用
print(per1)
print(per2)

輸出:

num = 3
num = 1
num = 2

更多關(guān)于Python相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Python面向?qū)ο蟪绦蛟O(shè)計(jì)入門與進(jìn)階教程》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python編碼操作技巧總結(jié)》及《Python入門與進(jìn)階經(jīng)典教程

希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。

相關(guān)文章

最新評(píng)論

靖宇县| 新巴尔虎右旗| 松滋市| 石嘴山市| 潮州市| 平阴县| 文成县| 叙永县| 湘潭县| 定边县| 定西市| 双柏县| 图们市| 芷江| 仲巴县| 聂拉木县| SHOW| 宁陕县| 确山县| 锡林浩特市| 高雄市| 垫江县| 平阳县| 广丰县| 青田县| 社旗县| 肃北| 新疆| 弋阳县| 蛟河市| 新余市| 琼中| 江源县| 庆元县| 安达市| 桐柏县| 油尖旺区| 吴川市| 金堂县| 长泰县| 鄱阳县|