面向对象学习

面向对象学习

1,对class类与object对象的认识

类是一种抽象的定义,不存在于现实世界,而对象则是类在现实世界的具体化。
类来源于对万物的认知划分归类,将一些有共性的物体归于一类。比如图书馆划分图书种类,超市划分商品种类。在图书馆或是超市某类图书或是某类商品你是不可能拿到的,只能拿到归属于此类之下的商品。在这种情况之下,商品或是书籍就是此类的“实例化”。这实际上就是python中的类与对象的一个案例。

对象是类实例化(具体体现),类必须经过实例化才能去使用。

2,子类与超类

一个类的对象为另一个类的对象的子集时,前者即为后者的子类,后者则为超类。子类可以使用超类所有的方法,但是如果子类不应具备是则要单独设置已覆盖该方法。

3,三大特性:封装、多态、继承

class Chinese:
    country = 'China'                          #数据属性
    l = ['a','b']
    def __init__(self,name):                    #函数属性
        self.name = name

    def dancing(self,dance):
        print('%s 正在 %s' % (self.name,dance))

p1 = Chinese('bob')
print(p1.l)
p1.l = [1,2,3]
p1.l.append('c')
print(p1.__dict__)
print(Chinese.l)
#修改对象的属性不会影响类的属性
print(Chinese.country)      #查
Chinese.country = '中国'     #改
Chinese.mascot = '熊猫'      #增
print(Chinese.__dict__)
del Chinese.country          #删   
print(Chinese.__dict__)
['a', 'b']
{'name': 'bob', 'l': [1, 2, 3, 'c']}
['a', 'b']
China
{'__module__': '__main__', 'country': '中国', 'l': ['a', 'b'], '__init__': <function Chinese.__init__ at 0x00000000058E7730>, 'dancing': <function Chinese.dancing at 0x00000000058E77B8>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None, 'mascot': '熊猫'}
{'__module__': '__main__', 'l': ['a', 'b'], '__init__': <function Chinese.__init__ at 0x00000000058E7730>, 'dancing': <function Chinese.dancing at 0x00000000058E77B8>, '__dict__': <attribute '__dict__' of 'Chinese' objects>, '__weakref__': <attribute '__weakref__' of 'Chinese' objects>, '__doc__': None, 'mascot': '熊猫'}

继承与派生

子类通过继承获得父类的属性,super() 子类调用父类方法,类似于函数的作用域,优先寻找自己的属性,找不到再向上寻找父类。

class Dad:
    '父类'
    money=20000
    money2 = 500
    def __init__(self,name):

        self.name=name


class Son(Dad):
    money = 100000

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

p1 = Son('bob',21)
print(p1.money)
print(p1.money2)
100000
500

新式类的继承顺序。优先左侧继承顺序查找,最后查找顶级。通过内置方法mro或mro()查看继承顺序

派生:子类增加自己独有的属性,或是将父类属性重新定制成自己独有的属性,而不影响父类属性。

class Hero:
    def __init__(self,name,gender,life_value,aggressivity):
        self.name = name
        self.gender = gender
        self.life_value = life_value
        self.aggressivity = aggressivity

    def attack(self,enemy):
        enemy.life_value -= self.aggressivity

class Songoku(Hero):
    camp = "immortal"
    def __init__(self,name,gender,life_value,aggressivity,skin):
        #Hero.__init__(self,name,gender,life_value,aggressivity)
        super().__init__(name,gender,life_value,aggressivity)
        self.skin = skin
        self.equip = Equip()                                #组合

    def attack(self,enemy):
        super().attack(enemy)
        print('%s 发动普通攻击' % self.name)

class Gyuumaou(Hero):
    camp = "goblin"
    def __init__(self, name, gender, life_value, aggressivity, skin):
        #Hero.__init__ (self, name, gender, life_value, aggressivity)
        super().__init__(name, gender, life_value, aggressivity)
        self.skin = skin

    def attack(self, enemy):
        super().attack (enemy)
        print ('%s 发动普通攻击' % self.name)

class Equip:
    def thump(self):
        print('重击使敌人晕眩')



h1 = Songoku('新手上路','male',1000,500,'Monkey King')
h2 = Gyuumaou('老牛','male',800,300,'demon')
h1.attack(h2)
h1.equip.thump()
新手上路 发动普通攻击
重击使敌人晕眩

组合

一个类中使用另一个类的对象作为数据属性

抽象类

抽象类:从类中抽象而来,不会有具体的存在,故不会被实例话,抽象类中只有抽象方法,只能被继承。

通过abc模块@abstractmethod(抽象方法)要求子类必须实现某一函数方法。
抽象类的本质还是类,统合了一组类的相似性(数据属性和函数属性;而接口只强调函数属性的相似性。抽象类同时具备类和接口的部分特性,可以实现归一化设计

import abc
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def move(self):
        print('子类必须能够活动')

    def touch(self):
        print('子类必须有触感')

class Cat(Animal):                  #没有实现抽象方法会报错
    pass

c1 = Cat()
---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-5-987e21bed3e6> in <module>()
     11     pass
     12 
---> 13 c1 = Cat()


TypeError: Can't instantiate abstract class Cat with abstract methods move
import abc
class Animal(metaclass=abc.ABCMeta):
    @abc.abstractmethod
    def move(self):
        print('子类必须能够活动')

    def touch(self):
        print('子类必须有触感')

class Bird(Animal):
    def move(self):
        print('鸟类大部分是可以飞翔的')

    def touch(self):
        print('鸟类是有感觉的')

b1 = Bird()
b1.move()
鸟类大部分是可以飞翔的

多态

多态指的是一类事物具有多种形态。如动物有鸟,狗,猫等等
多态性(多态动态绑定)是指不考虑实例类型的情况下使用实例,多态性分为静态多态性和动态多态性。
静态多态性:如任何相同类型之间都可以使用“+”
动态多态性:

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

class Cat(Animal):
    def talk(self):
        print('miao...')

class Bird(Animal):
    def talk(self):
        print('jiu...')

class Dog(Animal):
    def talk(self):
        print('wang...')

def talk(obj):                     #定义一个统一接口
    obj.talk()

c1 = Cat()
b1 = Bird()
d1 = Dog()

c1.talk()
b1.talk()
d1.talk()

talk(b1)
talk(c1)
talk(d1)
miao...
jiu...
wang...
jiu...
miao...
wang...

1,用同一形式调用,增加了程序的灵活与方便
2,无须修改其他代码即可添加新的种类,增加了程序可扩展性

封装

封装:隐藏逻辑,让使用者只需要使用给定方法不需要在意逻辑;单双下划线隐藏属性和方法。外部使用时“看不到”。
封装明确区分内外,内部可以直接使用而外部“不能用”

双下划线隐藏时会变成类名_

将数据属性隐藏起来后对外提供接口,可以加上限制条件以便控制数据属性。

class Examinee:
    def __init__(self,name,gender,age):
        self.__name = name
        self.gender = gender
        self.__age = age

    def set_info(self,name,age):
        if not isinstance(name,str):
            print('姓名必须是字符串')
        if not isinstance(age,int):
            print('年龄必须是整型')
        self.__name = name
        self.__age = age

    def tell_info(self):
        print("考生姓名:%s 年龄:%s" % (self.__name,self.__age))

e1 = Examinee('Bob','male',14)
e1.tell_info()

e1.set_info('Ben',15)
e1.tell_info()
考生姓名:Bob 年龄:14
考生姓名:Ben 年龄:15

封装另一方面隔离复杂功能,更能隐藏重要信息

@property #静态属性 #函数属性调用时可以省略(),看起来像数据属性一样,封装的一种形式,隐藏背后逻辑

class Student:
    def __init__(self,val):
        self.__Name = val

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

    @name.setter
    def name(self,val):
        if not isinstance(val,str):
            raise TypeError('必须输入字符串')
        self.__Name = val

    @name.deleter
    def name(self):
        raise TypeError('不能删除名字')

s1 = Student('Bob')
print(s1.name)
s1.name = 'Ben'
print(s1.name)
#del s1.name
Bob
Ben

绑定方法与非绑定方法

绑定方法:一个是绑定类并且只有类才可以使用,类在使用时自动传入参数,通过@classmethod装饰器实现。
另一个是绑定对象,类内定义的普通函数,使用时自动传参;对类来说就是一个普通函数,使用时需要传入参数。

# setting.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
name = 'bob'
age = '16'
gender = 'male'
import setting,hashlib,time
class Student:
    def __init__(self,name,age,gender):
        self.id = self.creat_id()
        self.name =name
        self.age =age
        self.gender =gender
    @property                               #静态属性,绑定到对象的方法   
    def tell_info(self):
        print('学生姓名:%s 年龄:%s 性别:%s 学号:%s' % (self.name,self.age,self.gender,self.id))

    @classmethod                            #类方法,绑定到类
    def from_conf(cls):
        obj = cls(setting.name,setting.age,setting.gender)
        return obj

    @staticmethod                           #静态方法:类内的工具包------非绑定方法 
    def creat_id():
        m = hashlib.md5(str(time.time()).encode('utf8'))
        return m.hexdigest()

s1 = Student.from_conf()
s1.tell_info

反射

反射:通过字符串的形式操作对象属性。hasattr , getattr , setattr , delattr。使用反射可以实现可插拔机制,越过未开发的组件继续开发接下来的功能。

class Server:
    def run(self):
        while True:
            inp = input('>>>:').strip()
            cmds = inp.split()

            if hasattr(self,cmds[0]):                 #hasattr判断对象是否有某方法
                func = getattr(self,cmds[0])           #getattr获取方法并赋值给func
                func(cmds)                             #func传入参数

    def get(self,cmds):
        print('get......',cmds)

    def put(self,cmds):
        print('put......',cmds)

obj = Server()
obj.run()
class Foo():
    pass

class Goo(Foo):
    pass

class Bar(Goo):
    pass

obj = Foo()
print(isinstance(obj,Foo))     #检查obj是否是后者对象
print(issubclass(Bar,Foo))     #检查Bar是否是后者派生类

内置方法

双下划线开头,自动运行

1,setitem , getitem ,delitem :像字典一样使用对象的属性

class Foo:
    def __init__(self,name):
        self.name = name

    def __getitem__(self, item):
        return self.__dict__[item]

    def __setitem__(self, key, value):
        self.__dict__[key] = value

    def __delitem__(self, key):
        self.__dict__.pop(key)

f1 = Foo('bob')
f1['age'] = 19
f1['age'] = 16
f1['gender'] = 'male'
print(f1['age'])
del f1['age']
print(f1.__dict__)

2,str:打印对象时自动触发,打印所返回字符串


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

    def __str__(self):
        print('运行次方法')
        return 'name:%s age:%s'%(self.name,self.age)

s1 = Student('bob',15)
print(s1)

3,del:删除对象前自动运行该操作(主动删除时,或是程序结束之前自动运行;可以用作回收系统资源)

class Open:
    def __init__(self,filename):
        print('open file.....')
        self.filename = filename

    def __del__(self):
        print('回收操作系统资源:self.close()')

f = Open('setting.py')
print('main---->')
print('end')

open file…..
main—->
end
回收操作系统资源:self.close()

猜你喜欢

转载自blog.csdn.net/marvin_wind/article/details/80233031
今日推荐