面向对象编程

137 阅读3分钟

init 方法定制对象特有的属性

class LuffyStudent:
    school='luffycity'
                stu1, '王二丫', '女', 18
    def __init__(self,name,sex,age):
        self.Name=name
        self.Sex=sex
        self.Age=age
后产生对象
stu1=LuffyStudent('王二丫','女',18) #LuffyStudent.__init__(stu1,'王二丫','女',18)
加上__init__方法后,实例化的步骤
 1、先产生一个空对象stu1
 2、LuffyStudent.__init__(stu1,'王二丫','女',18)
查
print(stu1.__dict__)
改
 stu1.Name='李二丫'
删除
del stu1.Name
print(stu1.__dict__)
增
stu1.class_name='python开发'
print(stu1.__dict__)

属性的查找 dict

继承

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

def f2(self):
    print('from Foo.f2')
    self.f1() #b.f1()

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

b=Bar()

print(b.dict)

b.f2()

多态

#多态:同一类事物的多种形态
import abc
class Animal(metaclass=abc.ABCMeta): #同一类事物:动物
    @abc.abstractmethod
    def talk(self):
        pass

class People(Animal): #动物的形态之一:人
    def talk(self):
        print('say hello')

class Dog(Animal): #动物的形态之二:狗
    def talk(self):
        print('say wangwang')

class Pig(Animal): #动物的形态之三:猪
    def talk(self):
        print('say aoao')

class Cat(Animal):
    def talk(self):
        print('say miamiao')

#多态性:指的是可以在不考虑对象的类型的情况下而直接使用对象

重用父类

#在子类派生出的新的方法中重用父类的方法,有两种实现方式 #方式一:指名道姓(不依赖继承)

# class Hero:
#     def __init__(self,nickname,life_value,aggresivity):
#         self.nickname=nickname
#         self.life_value=life_value
#         self.aggresivity=aggresivity
#     def attack(self,enemy):
#         enemy.life_value-=self.aggresivity
#
#
# class Garen(Hero):
#     camp='Demacia'
#
#     def attack(self,enemy):
#         Hero.attack(self,enemy) #指名道姓
#         print('from Garen Class')

# class Garen(Hero):
#     camp='Demacia'
#
#     def __init__(self,nickname,life_value,aggresivity,weapon):#添加weapon属性
#         # self.nickname=nickname
#         # self.life_value=life_value
#         # self.aggresivity=aggresivity
#         Hero.__init__(self,nickname,life_value,aggresivity)#重用父类的属性,
#
#         self.weapon=weapon

#方式二:super() (依赖继承)
# class Hero:
#     def __init__(self,nickname,life_value,aggresivity):
#         self.nickname=nickname
#         self.life_value=life_value
#         self.aggresivity=aggresivity
     def attack(self,enemy):
         enemy.life_value-=self.aggresivity


class Garen(Hero):
     camp='Demacia'
#
#     def attack(self,enemy):
#         super(Garen,self).attack(enemy) #依赖继承
#         print('from Garen Class')

# class Garen(Hero):
#     camp='Demacia'
#
#     def __init__(self,nickname,life_value,aggresivity,weapon):
#         # self.nickname=nickname
#         # self.life_value=life_value
#         # self.aggresivity=aggresivity
#
#         # super(Garen,self).__init__(nickname,life_value,aggresivity)
#         super().__init__(nickname,life_value,aggresivity)  #python3内已经简化super()
#         self.weapon=weapon 

super 是依赖于继承的

是参照哪一个对象的mro列表的顺序来继承

组合,可以实例化一个对象,将对象的属性等于另一个类的对象的属性,是什么有什么的关系

抽象类 只能被继承,不能被实例化,规范接口

import abc

class Animal(metaclass=abc.ABCMeta): #只能被继承,不能被实例化

all_type='animal'

@abc.abstractmethod
def run(self):
    pass

@abc.abstractmethod
def eat(self):
    pass

类的封装的属性,就是明确的区分内外,控制外部对隐藏属性的操作行为

这种变形的特点:
    1、在类外部无法直接obj.__AttrName
    2、在类内部是可以直接使用:obj.__AttrName
    3、子类无法覆盖父类__开头的属性


class A:
    def __foo(self): #_A__foo
        print('A.foo')

    def bar(self):
        print('A.bar')
        self.__foo() #self._A__foo()

class B(A):
    def __foo(self): #_B__foo
        print('B.foo')

b=B()
b.bar()

封装方法:

一:封装数据属性:明确的区分内外,控制外部对隐藏的属性的操作行为

二、 封装方法:隔离复杂度

class ATM:
    def __card(self):
        print('插卡')
    def __auth(self):
        print('用户认证')
    def __input(self):
        print('输入取款金额')
    def __print_bill(self):
        print('打印账单')
    def __take_money(self):
        print('取款')

    def withdraw(self):
        self.__card()
        self.__auth()
        self.__input()
        self.__print_bill()
        self.__take_money()
a=ATM()
a.withdraw()
class Room:
    def __init__(self,name,owner,weight,length,height):
        self.name=name
        self.owner=owner

        self.__weight=weight
        self.__length=length
        self.__height=height

    def tell_area(self):
        return self.__weight * self.__length * self.__height

r=Room('卫生间','alex',10,10,10)

# print(r.tell_area())

print(r.tell_area())

property装饰器的作用

将类中的函数方法修饰成属性一样,让对象来调用

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

    @property
    def name(self):
        # print('getter')
        return self.__name

    @name.setter
    def name(self,val):
        # print('setter',val)
        if not isinstance(val,str):
            print('名字必须是字符串类型')
            return
        self.__name=val
    @name.deleter
    def name(self):
        print('deleter')

        print('不允许删除')

将类中函数的方法伪装成函数的属性,供使用者调用

类内部定义的函数可以分成2大类:

绑定方法:绑定给对象的方法,在类内定义的没有被装饰器修饰的方法,绑定给谁就由谁来调用 绑定到类的方法,在类内被装饰器classmethod修饰的方法

非绑定方法:就是普通方法,没有自动传值,对象和类都是调用,用@staticmethod修饰

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

    def tell(self):
        print('名字是%s' %self.name)

    @classmethod
    def func(cls): #cls=Foo
        print(cls)

    @staticmethod
    def func1(x,y):
        print(x+y)

反射的应用:

class Service:
    def run(self):
        while True:
            inp=input('>>: ').strip() #cmd='get a.txt'
            cmds=inp.split() #cmds=['get','a.txt']

            # print(cmds)
            if hasattr(self,cmds[0]):   #hasattr()函数判断对象是否包含对应的属性
                func=getattr(self,cmds[0])  #getattr() 函数用于返回一个对象属性值。
                func(cmds)
    def get(self,cmds):
        print('get.......',cmds)
    def put(self,cmds):
        print('put.......',cmds)

obj=Service()
obj.run()