面向对象笔记基础

Posted fqh202

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面向对象笔记基础相关的知识,希望对你有一定的参考价值。

面向对象基础笔记

面向过程
面向对象
类的初步理解
__init__方法的理解
区分类的属性与对象的属性
继承:派生 组合
抽象类
多态与多态性
封装: 类和对象的隐藏属性


面向过程

核心是过程,即解决问题的步骤,比如设计一条流水线, 是机械的思维方式。

  • 优点: 将复杂的问题流程化,进而简单化;
  • 缺点: 可扩展性差;

面向对象

  • 对象就是属性与方法的结合体.
    • 优点: 可扩展性强;
    • 缺点: 编程复杂度高;
    • 应用场景:应对客户不停变化的需求,尤其是互联网应用,游戏和企业内部的应用。

类的初步理解

  • 类是一系列具有相似特征与方法的对象的集合。

  • 在现实世界中,是先有对象,然后才有类;在程序中,一定是先有类,将类实例化后才有对象。

  • 在类定义完成的那一刻会直接生成一个类的内部命名空间,而函数是只有被调用时才会生产内部命名空间。

  • 类的属性
    • 1.数据属性:类的数据属性是共享的,占用同一个内存地址, 无论是对象访问还是类本身访问都是相同的内幕才能地址(不包括__init__创建的特有数据属性);
    • 2.函数属性:是绑定给类的实例化对象的使用的,绑定到不同的对象是不同的方法,对象调用绑定方法时候,会把对象当做第一个参数传入,但是类调用函数的时候访问的是另外一个函数内存地址,且不会主动将自己作为第一个参数传入进去;
  • 类的用途:
    • 1.类可以通过‘.’访问类的数据属性或者函数属性,并且可以对齐进行增加、删除、修改数据属性操作;
    • 2.类名加上( )就直接实例化了一个类对象

__init__方法的理解

  • 对象可以定制自己独有的特征,是类实例化对象的局部命名空间,可以通过类名.__dict__访问
  • 类实例化后若检测到此放回会自动调用此方法
  • 类的公共的属性和方法放在类里边,相当于类的命名空间,

具体的实例化的步骤:

  1. 先产生一个空对象 jack = People()
  2. 然后调用__init__方法,jack对象和参数都传进__init__(self,name, age, gender),对obj绑定对象数据属性,self.Name = name.....
  3. 可以通过jack,.__dict__方法访问类的命名空间,里面就有Name,Age,Gender等自己属性和值了

区分类的属性与对象的属性

  • 类的属性是可以共享的,对象和类都可以访问

  • 但是通过__ini__定义的属性是对象独有的,只有对象可以访问,类是不能访问的,也可以直接用对象.

  • 赋值属性, 若查询不到属性,会直接向上在对象的类的命名空间查找,类有父类,会继续上溯父类的命名空间查找


继承

  • 理解: 类与类之间的关系,类a继承类b,那么可以理解为类a是类b。
  • python中支持多继承
  • 作用:代码重用,减少代码重复

python2:

  • 经典类:没有继承object的类以及它的子类都称为经典类,深度优先查找
  • 新式类:与经典类相反,广度优先查找

python3默认都是新式类,都是继承object类


派生

在子类派生出的方法属性中重用父类的方法,有两种实现方式:

  1. 指名道姓,不依赖于继承
  2. super(),依赖于继承关系,在当前函数内部生生成一个父类对象,super(当前类名,self).父类的属性直接可以调用父类的数据属性与方法属性,在python3中可以直接使用用self()来生成父类对象
  3. super是沿着子类的mro()这个继承列表进行查询属性的

组合

在现实世界中,类之间可能存在是与不是 或者 有或没有的关系,比如,学生可以有很多课程,那么可以在学习实例化对象小明的增加课程1,课程2等等属性,那么小明可以直接访问课程1,2等课程对象,也就可以访问课程类的属性与方法了!

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

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

    def sit_down(self):
        print(‘dog %s is sitting dowm‘ % self.name)


p1 = People(‘jim‘)
dog1 = Dog(‘将军‘)
dog2 = Dog(‘旺旺‘)

p1.Dog1 = dog1  # 给jim增加第一只狗
p1.Dog2 = dog2  # jim收养了第二只狗
p1.Dog1.sit_down()  # dog 将军 is sitting dowm
p1.Dog2.sit_down()  # dog 旺旺 is sitting dowm

print(p1.__dict__)  # {‘dog1‘: <__main__.Dog object at 0x7f87b7aaba58>, ‘name‘: ‘jim‘, ‘dog2‘: <__main__.Dog object at 0x7f87b7aaba90>}

抽象类

从实现角度来看,抽象类与普通类的不同之处在于:抽象类中只能有抽象方法(没有实现功能),该类不能被实例化,只能被继承,且子类必须实现抽象方法。这一点与接口有点类似,但其实是不同的

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

class Dog(Animal):
    def run(self):
        print(‘dog is running‘)

    # def speak(self):
    #     print(‘dog is barking‘)

d = Dog()
d.run()
# d.speak()
  • 在若子类继承抽象父类,那么子类必须实现父类的抽象方法,否则子类的实例化过程就会报错

多态与多态性

多态:同一类事物的多种形态
多态性:指在不考虑实例类型的情况下使用实例,多态性分为静态多态性和动态多态性

多态性的好处:

  • 1.增加了程序的灵活性, 以不变应万变,不论对象千变万化,使用者都是同一种形式去调用
peo=People()
dog=Dog()
pig=Pig()

# peo、dog、pig都是动物,只要是动物肯定有talk方法
# 于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
peo.talk()
dog.talk()
pig.talk()

# 更进一步,我们可以定义一个统一的接口来使用
def func(obj):
    obj.talk()
    • 2.增加了程序额可扩展性,通过继承父类创建了一个新的类,使用者无需更改自己的代码,还是用同一个接口去调用
  • 鸭子类型: Python崇尚鸭子类型,即‘如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子,python程序员通常根据这种行为来编写程序。例如,如果想编写现有对象的自定义版本,可以继承该对象,也可以创建一个外观和行为像,但与它无任何关系的全新对象,后者通常用于保存程序组件的松耦合度

封装

类和对象的隐藏属性

  1. 采用双下划线加属性名称定义的属性;
  2. 在类内部可以直接通过obj.__atrrname调用,但是在外部不能通过obj.__atrrname名称调用;
  3. 子类无法覆盖父类以‘__‘开头的属性, 因为子类的属性和父类的属性名转换后是不一样的,前面加了_类名的前缀;
  4. 在类定义的阶段隐藏属性可以生效,但是在定义完成后再想隐藏属性是没有用的,即随后通过调用类名或对象定义隐藏属性不会自动转换属性名称
  • 隐藏属性的作用
    • 封装数据属性:明确区分内外,控制外部对隐藏属性的操作行为
class Teacher:
    def __init__(self,name,age):
        self.__name=name
        self.__age=age
    def tell_info(self):
        print(‘姓名:%s,年龄:%s %(self.__name,self.__age))
    def set_info(self,name,age):
        if not isinstance(name,str):
            raise TypeError(‘姓名必须是字符串类型‘)
        if not isinstance(age,int):
            raise TypeError(‘年龄必须是整型‘)
        self.__name=name
        self.__age=age

t=Teacher(‘egon‘,18)
t.tell_info()

t.set_info(‘egon‘,19)
t.tell_info()
  • 封装方法:隔离复杂度
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()
  • 解释:取款是功能,而这个功能有很多功能组成:插卡、密码认证、输入金额、打印账单、取钱
    对使用者来说,只需要知道取款这个功能即可,其余功能我们都可以隐藏起来,很明显这么做
    隔离了复杂度,同时也提升了安全性

  • 封装还可以体现出可扩展性高的优点


property的应用

class People:
    def __init__(self, name, age, sex):
        self.__name = name
        self.__sex = sex
        self.__age = age

    @property
    def info(self):
        print(‘姓名:<{name}> 年龄:<{age}> 性别:<{sex}>‘.format(name=self.__name, age=self.__age, sex=self.__sex))

p1 = People(‘jim‘, 28, ‘male‘)
p1.info

类内部的方法分类

在类内部定义的函数,分为两大类:

  1. 绑定方法:绑定给谁,就应该由谁去调用,谁来调用就把调用者当做第一个参数自动传入。对象和类都可以调用,仅仅的区别在于传输的参数
    • 绑定到对象的方法: 在类内部定义的没有被任何装饰器修饰的函数;
    • 绑定到类的方法: 在类内部定义且有装饰器classmethod修饰的方法
  2. 非绑定方法: 在类的内部定义,被装饰函数staticmethod修饰的函数。它不能自动传值, 不能与类或者对象绑定,任何对象或者类都可以调用,就是一个普通的函数
class Account:

    bank=‘CBC‘
    def __init__(self, username, password, balance):
        self.__Username = username
        self.__Password = password
        self.__balance = balance

    def charge(self, amount):
        if not isinstance(amount, int):
            print(‘请输入数字金额‘)
            return
        if int(amount) < 0:
            print(‘输入金额有误‘)
            return
        self.__balance += amount

    def check_account(self):
        print(‘账户余额: %s % self.__balance)

    @classmethod  # 绑定到类的方法
    def check_bank(cls):
        print(‘所属银行:<%s>‘ % cls.bank)

    @staticmethod  # 静态方法,非绑定方法
    def del_bank():
        del Account.bank

反射

通过字符串来映射到对象的属性

  • hasattr(obj, ‘key‘),判断对象obj内部有没有key这个属性名;
  • getattr(obj, ‘key‘, None),获取对象obj内部的key的属性,相当于obj.key,若没有返回空;
  • setattr(obj, ‘key‘, ‘value‘), 可以直接增加obj的key的属性,并将其值设定为value
  • delattr(obj, ‘key‘), 删除obj对象的属性值
class fileObj:
    def read(self):
        print(‘read files‘)

    def write(self):
        print(‘write files‘)

    def command(self):
        while True:
            command = input(‘>>> ‘).strip()
            if not command:
                print(‘不能为空‘)
                return
            if hasattr(self,command):
                fun =getattr(self, command)
                fun()
                break

file = fileObj()
file.command()

以上是关于面向对象笔记基础的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段9——JS中的面向对象编程

基础笔记二 面向对象编程

python学习笔记-面向对象基础

面向对象笔记基础

Java基础学习笔记五 Java基础语法之面向对象

Python学习笔记——基础篇第六周——面向对象