类的三大特性(一)

一、继承

1. 基本

私有变量 self.name

直接定义 属于类的方法 相当于 static

2. 继承

属性查找 就近原则

3. 派生

重写,以自己的为准

使用 父类方法 super().

4. 经典类与新式类

  • 新式类: 继承 object 的类,以及该类的子类孙子类,都是新式类
  • 经典类: 没有继承object的类,以及该类的子类,孙子类,都是经典类

5. 多继承属性查找

  • 经典类:多继承情况下,再要查找属性不存在时,会按照深度优先的方式查找下去
  • 新式类: 多继承情况下,再要查找属性不存在时,会按照广度优先的方式查找下去

属性查找方法: __mor__

class A(object):
    def test(self):
        print("form A")


class B(A):
    def test(self):
        print("form B")


class C(A):
    def test(self):
        print("form C")


class D(B):
    def test(self):
        print("form D")


class E(C):
    def test(self):
        print("form E")


class F(D, E):
    pass


f1 = F()
f1.test()
print(F.__mro__)

# answer
form D
(<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)

6. super() 继承查找

class X:
    def test(self):
        print('X')

    def f1(self):
        print('XF')


class A(X):
    def test(self):
        print('1 打印')
        super().f1()
        print('3 打印')


class B:
    def f1(self):
        print('2 from B')


class C(A, B):
    pass

c = C()
c.test()
print(C.__mro__)

# answer
1 打印
XF
3 打印
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.X'>, <class '__main__.B'>, <class 'object'>)

super调用和用父类名字调用,各有优劣,不能混着用。

7. 组合

一个类产生的对象,该对象拥有一个属性,这个属性的只是来自于另外一个类的对象

class Date:
    def __init__(self, year, mon, day):
        self.year = year
        self.mon = mon
        self.day = day

    def tell_birth(self):
        print("出生年月<%s-%s-%s>" % (self.year, self.mon, self.day))


class People:
    school = 'syau'

    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        self.gender = gender


class Teacher(People):
    def __init__(self, name, age, gender, level, salary):
        super().__init__(name, age, gender)
        self.level = level
        self.salary = salary

    def change_score(self):
        print("teacher %s is changing score " % self.name)


class Student(People):
    def __init__(self, name, age, gender, course):
        super().__init__(name, age, gender)
        self.course = course

    def choose(self):
        print("student %s is chose course" % self.name)


teal = Teacher('Albert', 18, 'male', 10, 3.1)
date_obj = Date(2000, 1, 1)
date_obj.tell_birth()
teal.birth = date_obj
print(teal.birth)
teal.birth.tell_birth()
teal.change_score()
stu1 = Student('张三', 16, 'male', 'AI')
stu1.birth = Date(2000, 3, 3)
stu1.birth.tell_birth()
# answer
出生年月<2000-1-1>
<__main__.Date object at 0x7fcccb2c8210>
出生年月<2000-1-1>
teacher Albert is changing score 
出生年月<2000-3-3>

解决代码重用问题的两种方案:继承、组合

二、封装

1. 封装基本介绍

封装的目的就是为了明确区分内外,对外不是隐藏的,对内部是开放的。

class Foo2:
    __x = 111
    def __init__(self, y):
        self.__y = y
    def __f1(self):
        print('Foo.f1')


# x,y,f1 都访问不到了
obj2 = Foo2(222)
print(obj2.x)
print(obj2._x)
print(obj2.__x)
print(obj2.f1)
print(obj2.__f1)
print(obj2.y)
print(obj2.__y)

为一个属性名加__开头,会在类定义阶段将属性名变形:
__属性名 ==> _类名__属性名
注: 类定义阶段执行类体内的代码(类体内的函数只检测语法,不执行)

类的命名空间

在外部访问隐藏属性

不建议下面的访问方式,因为__ 就是为了隐藏内部变量

print(obj2._Foo2__x)
print(obj2._Foo2__f1)
print(obj2._Foo2__y)

# answer
111
<bound method Foo2.__f1 of <__main__.Foo2 object at 0x7fe0c0fd2950>>
222

使用 函数访问隐藏属性

class Foo3:
    __x = 111

    def __init__(self, y):
        self.__y = y

    def __f1(self):
        print('Foo.f1')

    def get__y(self):
        return self.__y

obj3 = Foo3(222)
print(obj3.get__y())
# asnwer
222

父类不让子类覆盖自己的方法

class Foo:
    def __f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.__f1()


class Bar(Foo):
    def __f1(self):
        print('Bar.f1')

obj4 = Bar()
obj4.f2()
# answer
Foo.f2
Foo.f1

2. Property方法

property 本质也是封装,不过现在是别人封装好了,相当于把一个对象的函数属性伪装成了变量属性,强大之处在于他可以动态变化

class People:
    def __init__(self, name, weight, height):
        self.name = name
        self.weight = weight
        self.height = height

    @property
    def bmi(self):
        return self.weight / (self.height * self.height)


albert = People('albert', 68, 1.68)
print(albert.name)
print(albert.bmi)
albert.weight = 65
print(albert.bmi)
# asnwer
albert
24.092970521541954
23.030045351473927

3. 伪装属性的修改与删除

class People:
    def __init__(self, name):
        self.__name = name

    @property
    def name(self):
        print('访问'.center(50, '='))
        return self.__name

    @name.setter
    def name(self, x):
        print('修改'.center(50, '='))
        self.__name = x

    @name.deleter
    def name(self):
        print('删除'.center(50, '='))
        del self.__name

p = People('albert')
print(p.name)
p.name = 'Albert'
print(p.name)
del p.name
print(p.name)

# answer
========================访问========================
albert
========================修改========================
========================访问========================
Albert
========================删除========================

三、多态

多肽与多态性

  • 函数名一样
  • 四个函数缺一不可
import abc  # abstract class


class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def eat(self):
        pass

    @abc.abstractmethod
    def drink(self):
        pass

    @abc.abstractmethod
    def run(self):
        pass

    @abc.abstractmethod
    def bark(self):
        pass


class Cat(Animal):
    def eat(self):
        pass

    def drink(self):
        pass

    def run(self):
        pass

    def bark(self):
        print('喵喵')




class Dog(Animal):
    def eat(self):
        pass

    def drink(self):
        pass

    def run(self):
        pass

    def bark(self):
        print('汪汪')


class Pig(Animal):
    def eat(self):
        pass

    def drink(self):
        pass

    def run(self):
        pass

    def bark(self):
        print('哼哼')


c = Cat()
d = Dog()
p = Pig()
c.bark()
d.bark()
p.bark()
# asnwer
喵喵
汪汪
哼哼

# 追加
def BARK(animal):
    animal.bark()


BARK(c)
BARK(d)
BARK(p)
# answer
喵喵
汪汪
哼哼

鸭子类型(Duck Type)

python 推崇这种方式
只要长得像,不是也是,用这种方式,既解开了耦合,又同一了标准

class Disk:

    def read(self):
        print('disk read')

    def write(self):
        print('disk write')


class Txt:

    def read(self):
        print('txt read')

    def write(self):
        print('txt write')


class Process:

    def read(self):
        print('process read')

    def write(self):
        print('process write')


obj1 = Disk()
obj2 = Txt()
obj3 = Process()
obj1.read()
obj2.read()
obj3.read()

# answer
disk read
txt read
process read

类的绑定方法

import LSettings


class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def tell(self):
        print('%s %s' % (self.name, self.age))

    @classmethod
    def read_form_conf(cls):
        return People(LSettings.NAME, LSettings.AGE)


p = People.read_form_conf()
p.tell()
# asnwer
James 35

类的静态(非绑定)方法

import hashlib
import time

import LSettings


class People:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def tell(self):
        print('%s %s' % (self.name, self.age))

    @classmethod
    def read_form_conf(cls):
        return People(LSettings.NAME, LSettings.AGE)

    @staticmethod
    def create_id():
        m = hashlib.md5()
        m.update(str(time.process_time()).encode('utf-8'))
        return m.hexdigest()


p = People.read_form_conf()
p.tell()
print(People.create_id())
print(People.create_id)
print(p.create_id)
# answer
James 35
f8acdd09e3cf88f68069f62c5a2e924d
<function People.create_id at 0x7fcd48ac1560>
<function People.create_id at 0x7fcd48ac1560>

github仓库 https://github.com/yangxin6/python-basic.git

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值