Day15-note_property_method_inherit

Day 15

補(bǔ)充

__str__,__repr__

class Student:
    def __init__(self, name):
        self.name = name
    # 定制,單獨(dú)打印對(duì)象的時(shí)候的樣式,返回值是什么就打印什么(要求返回值的類型必須是字符串)
    # def __str__(self):
    #     # 打印的誰self就是誰
    #     return '<' + str(self.__dict__)[1:-1] + '>'

    def __repr__(self):
        return '<' + str(self.__dict__)[1:-1] + '>'


xiaoming = Student('小明')
xiaohua = Student('小花')
persons = [xiaoming, xiaohua]
print(xiaoming, xiaohua)
print(persons)

結(jié)果:

<'name': '小明'> <'name': '小花'>
[<'name': '小明'>, <'name': '小花'>]
1. 私有化

本質(zhì)上,python中所有的屬性和方法都是公開,在類的外部可以使用也可以被繼承。

  1. 私有化 -- 讓屬性和方法只能在類的內(nèi)部使用,不能在類的外部使用
    1)語法:
聲明屬性或者方法的時(shí)候,在屬性名或者方法名前加"__"

2)python私有化的原理

python并不能像Java一樣從訪問權(quán)限上去限制屬性和方法,沒有真正的私有屬性和方法。
私有化只是在兩個(gè)下劃線開頭的名字前加前綴‘_類名’,導(dǎo)致不能直接通過原名進(jìn)行訪問
class Person:
    __num = 50

    def __init__(self, name, age=10):
        self.name = name
        self.age = age
        self.__gender = '男'

    def eat(self, food='米飯'):
        print(Person.__num)
        print('%s在吃%s' % (self.name, food))

    def __run(self):
        print('%s在跑步' % self.name)


p1 = Person('小明')
# print(Person.num)
print(p1.name)
p1.eat()
# AttributeError: type object 'Person' has no attribute '__num'
# print(Person.__num)
# p1.__run()    # AttributeError: 'Person' object has no att
  1. 對(duì)象屬性的保護(hù):
    不要直接訪問或者修改對(duì)象屬性的值,而是通過屬性訪問器(getter)和修改器(setter)去操作對(duì)象屬性
    需要添加getter或者setter的對(duì)象屬性,屬性命名的時(shí)候需要在最前面加'_'。
    (添加'_'的目的是為了告訴使用者,這個(gè)屬性我給它添加了getter或者setter)
    1)getter -- 獲取屬性的值(間接)
a.語法:
@property
def 函數(shù)名(self):
    return 屬性值
    
b.說明:
函數(shù)名  --  對(duì)應(yīng)的屬性名去掉下劃線
屬性值  --  和對(duì)應(yīng)的有下劃線的屬性值有關(guān)聯(lián)
c.什么時(shí)候用
如果希望在獲取某個(gè)屬性值之前干點(diǎn)別的事情,就給這個(gè)屬性添加getter

2)setter -- 給屬性賦值(間接)
想要添加setter必須先添加getter

a.語法:
@getter名.setter
def 函數(shù)名(self, 參數(shù)):
    其他語句
    self.屬性 = 值
    
b.什么時(shí)候用
如果在給屬性賦值之前需要桿端別的事情,就給這個(gè)屬性添加setter,
或者需要其中一個(gè)屬性賦值之后影響其他屬性,就給這個(gè)屬性添加setter
class Student:
    def __init__(self, name1):
        self._name = name1
        self._week = 1
        self._age = 0
        self.is_adult = False

    @property
    def name(self):
        return self._name

    @property
    def week(self):
        if self._week == 1:
            return '星期一'
        elif self._week == 2:
            return '星期二'
        elif self._week == 3:
            return '星期三'
        elif self._week == 4:
            return '星期四'
        elif self._week == 5:
            return '星期五'
        elif self._week == 6:
            return '星期六'
        elif self._week == 7:
            return '星期天'

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

    @age.setter
    def age(self, value):
        if value >= 18:
            self.is_adult = True
        else:
            self.is_adult = False
        self._age = value
        # if isinstance(value, int):
        #     if value < 0 or value > 200:
        #         print('年齡范圍只能在0~200')
        #         self._age = 0
        #     else:
        #         self._age = value
        #
        # else:
        #     print('年齡只能是整數(shù)!')
        #     self._age = 0


stu = Student('xiaoming')

# print(stu._name)
print(stu.name)     # 通過不帶下劃線去獲取屬性的值的時(shí)候,本質(zhì)是在調(diào)用屬性對(duì)應(yīng)的getter方法,結(jié)果是getter的返回值
print(stu.week)

stu.age = 1099323
# stu.age = 'abc'
class Circle:
    def __init__(self, r):
        self.r = r
        self._area = None

    @property
    def area(self):
        return self.r**2*3.1415926


c1 = Circle(2)
print(c1.area)

c1.r = 10
print(c1.area)
  • 練習(xí):聲明矩形類,有長、寬、周長、面積,要求修改長和寬的值得時(shí)候,周長和面積自動(dòng)變化,并且不能修改周長和面積的值
class WriteError(Exception):
    def __str__(self):
        return '嘗試修改一個(gè)只讀的屬性!'


class Rect:
    def __init__(self, length, width):
        self._length = length
        self._width = width
        self._area = length * width
        self._perimeter = (length + width) * 2

    # length
    @property
    def length(self):
        return self._length

    @length.setter
    def length(self, value):
        self._length = value
        self._area = self.length * self._width
        self._perimeter = (self.length + self._width) * 2

    # width
    @property
    def width(self):
        return self._width

    @width.setter
    def width(self, value):
        self._width = value
        self._area = self.length * self._width
        self._perimeter = (self.length + self._width) * 2


    @property
    def area(self):
        return self._area

    @area.setter
    def area(self, value):
        print('面積不能直接改修!')
        raise WriteError

    @property
    def perimeter(self):
        return self._perimeter

    @perimeter.setter
    def perimeter(self, value):
        print('周長不能直接改修!')
        raise WriteError

r1 = Rect(4, 5)
print(r1.area, r1.perimeter)
r1.width = 10
print(r1.area, r1.perimeter)
2. 類中的方法
  1. 類中的方法:對(duì)象方法、類方法、靜態(tài)方法
    1)對(duì)象方法
a.怎么聲明:直接聲明在類中
b.特點(diǎn):有默認(rèn)參數(shù)self;調(diào)用的時(shí)候不用傳參,指向當(dāng)前對(duì)象
c.怎么調(diào)用:通過對(duì)象來調(diào)用(對(duì)象.對(duì)象方法())
d.什么時(shí)候使用:如果實(shí)現(xiàn)函數(shù)的功能,需要使用對(duì)象屬性,就用對(duì)象方法

2)類方法

a.怎么聲明:聲明韓式前添加@classmethod裝飾器
b.特點(diǎn):有默認(rèn)參數(shù)cls;調(diào)用的時(shí)候不用傳參,系統(tǒng)將調(diào)用這個(gè)方法的類傳給它,指向當(dāng)前類
c.怎么調(diào)用:通過類來調(diào)用(類.類方法())
d.什么時(shí)候使用:在不需要對(duì)象屬性的前提下,需要類的字段,就使用類方法

3)靜態(tài)方法

a.怎么聲明:聲明前添加@staticmethod裝飾器
b.特點(diǎn):沒有默認(rèn)參數(shù)
c.怎么調(diào)用:通過類來調(diào)用(類.靜態(tài)方法())
d.什么時(shí)候使用:既不需要對(duì)象屬性也不需要類的字段,就使用靜態(tài)方法
class Person:
    num = 60

    def __init__(self, name='張三', age='18'):
        self.name = name
        self.age = age

    # 對(duì)象方法
    def eat(self, food):
        print('%s在吃%s' % (self.name, food))

    # 類方法
    @classmethod
    def show_count(cls):
        # cls:當(dāng)前類,當(dāng)前類能做的事情,cls都能做
        print('類方法', cls)
        print(Person.num)
        print(cls.num)   # 使用類的字段
        p = cls()   # 創(chuàng)建對(duì)象
        print(p)

    # 靜態(tài)方法
    @staticmethod
    def static():
        print('靜態(tài)方法',Person.num)
3. 繼承
class Person:
    num = 61

    def __init__(self):
        self.name = '小明'
        self.age = 0
        self.gender = '男'

    def eat(self, food):
        print('%s在吃%s' % (self.name, food))

    @staticmethod
    def run():
        print('人在跑步')

    def func(self):
        print('我是一個(gè)對(duì)象方法', self.name)
  1. 繼承
繼承者  --  子類
被繼承者  --  父類
繼承  --  讓子類直接擁有父類的屬性和方法

1)語法:

class 類名(父類):
    類的內(nèi)容
  1. 在子類中添加內(nèi)容
    1)在子類中添加字段和方法
直接在子類中聲明新的字段和方法
class Student(Person):
    num = 100
    id_pre = 'stu'

2)添加對(duì)象屬性

在子類中實(shí)現(xiàn)__init__方法,并且添加新屬性,同時(shí)需要通過super().__init__()去調(diào)用父類的init方法

補(bǔ)充:類中的函數(shù)的調(diào)用過程
先看當(dāng)前類中是否有這個(gè)方法,如果有直接調(diào)用自己的方法;沒有就去看父類有沒有這個(gè)方法,如果有就調(diào)用父類的方法;
如果父類也沒有就找父類的父類,以此類推,如果直到找到object都沒有找到這個(gè)方法,才會(huì)報(bào)錯(cuò)。

python中所有的類默認(rèn)都是繼承object,object是python中所有類的基類
class Person:
    pass
class Student(Person):
    # 1.添加對(duì)象屬性
    def __init__(self):
        # 調(diào)用當(dāng)前類的父類的__init__方法
        super().__init__()
        self.stu_id = '001'
        self.score = 0
        
    # 2.添加靜態(tài)方法
    @staticmethod
    def study():
        print('學(xué)習(xí)')
  1. 方法重寫
在子類中重新實(shí)現(xiàn)父類的函數(shù);可以通過super()去調(diào)用父類中的方法。
注意:super()不能在靜態(tài)方法中使用,只能在對(duì)象方法和類方法中用
class Person:
    pass
class Student(Person):
    # 3.方法重寫
    @classmethod
    def run(cls):
        # super().run()
        # cls.__bases__[0].run()
        print('學(xué)生在跑步')
        print('===========')

    def func(self):
        # super().func()
        self.__class__.__bases__[0]().func()
        print('+++++++++')

調(diào)用:

stu1 = Student()
# 繼承
print(Student.num)
stu1 = Student()
stu1.eat('喝湯')

# 添加字段和方法
print(Student.id_pre)
Student.study()
# 添加對(duì)象屬性
print(stu1.stu_id, stu1.score)
print(stu1.name, stu1.age, stu1.gender)
# 方法重寫
Student.run()
Person.run()
stu1.func()
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,641評(píng)論 1 32
  • 1.設(shè)計(jì)模式是什么? 你知道哪些設(shè)計(jì)模式,并簡要敘述?設(shè)計(jì)模式是一種編碼經(jīng)驗(yàn),就是用比較成熟的邏輯去處理某一種類型...
    龍飝閱讀 2,302評(píng)論 0 12
  • 面試題參考1 : 面試題[http://www.cocoachina.com/ios/20150803/12872...
    江河_ios閱讀 1,815評(píng)論 0 4
  • 第3章 基本概念 3.1 語法 3.2 關(guān)鍵字和保留字 3.3 變量 3.4 數(shù)據(jù)類型 5種簡單數(shù)據(jù)類型:Unde...
    RickCole閱讀 5,504評(píng)論 0 21
  • 我真正記事起是那次意外。 事情的起因我記得是用茅草桿去測池塘的水深。臨近過年的時(shí)候,村里的兩口池塘就開始放水捕魚。...
    月亮下的書蟲閱讀 726評(píng)論 0 1

友情鏈接更多精彩內(nèi)容