首页 > 其他分享 >面向对象

面向对象

时间:2022-08-22 08:22:28浏览次数:56  
标签:__ 调用 对象 self 面向对象 class 属性

1.什么是面向对象和面向过程编程思想

面向过程:

1.核心是‘过程’二字
2.过程的含义是将程序流程化
3.过程是流水线,用来分步骤解决问题的

面向对象:

1.核心是‘对象’二字
2.对象的含义是将程序进行整合
3.对象是‘容器’,用来盛放数据和功能(变量和函数)

总结:以做西红柿鸡蛋面为例:

面向过程:我需要买西红柿--》买鸡蛋、面--》把西红柿洗好、鸡蛋打好...等等
面向对象:找个人帮我干活,我只需要告诉那个人我需要吃西红柿鸡蛋面(调用该对象),具体的过程交给别人干。
image

python中可以用来盛放数据和功能的‘容器’可以是字典、列表、集合等。但是这些容器在存放功能的时候,并不能把功能的具体代码全部传进去(只能传一个函数名),这就有一定的局限性!

那么。python中提供了什么样的语法来让我们更好的存放数据和功能呢??

2.类

类,其实也是‘容器’,它是用来存放对象1、对象2、对象3...等共有的数据和功能!

它能够更好的节省空间并且帮我们更好完成面向对象的编程!

2.1 类的引入

# 所有类体中最常见的就是变量和功能的定义,但是类体中也可以包含其他代码
# 注意:类体中的代码是在定义阶段就会执行的,也就是说在定义阶段就开辟了名称空间

class ClassName: # 类的定义 class 类名:
    # 变量(数据)的定义
    var = 111
    # 功能的定义
    def send(self):
        pass

    def rcv(self):
        pass
		
# 类中提供了一个方法查看类的名称空间.__dict__,得到一个字典
print(ClassName.__dict__)
# __dict__[key]调用类体中的变量值或者功能
print(ClassName.__dict__['send'])
# 为了简便上述的调用方式,类提供了.变量/.函数名的方法来调用,注意不加括号
print(ClassName.send)

2.2 类的调用--产生对象

# 类的调用,类名()的方式返回了一个class_obj对象,就是把类和该对象建立了一个联系,该对象就可以使用类里面的定义的变量和功能了
class_obj = ClassName()

# 该对象的.__dict__方法得到的是一个空字典,可以使用对象.属性名=属性值的方式给该字典添加值
print(class_obj.__dict__)

# 类名.变量名/类名.函数名 调用类的变量和功能
print(class_obj.var)

2.3 类的__init__方法

当对象1、对象2、对象3...等的属性都一样,只是值不同的时候,我们不断的使用对象.属性=属性值给对象赋值的时候,不免需要个每个对象都这样操作,这样会使得代码冗余。

因此类中有一个 __init__的初始化方法,会自动帮你封装好这个对象独有的属性,你只需要在调用的时候传入对应的属性值就行。

image

class ClassName:
    # 参数self表示调用类时产生的对象,x和y是调用类时对应传人的参数
    def __init__(self,x,y):
        self.name = x
        self.age = y

# 调用类产生对象的操作,实际上是类的实例化的过程,这个过程发生了三件事
# 1.产生了一个空对象
# 2.自动调用类里面的__init__方法,并将调用时候的参数对应传给__init__方法
# 3.返回初始化好的对象class_obj
class_obj = ClassName('zhang',18)

总结:

1.该方法会在调用类的时候自动执行,用来为对象初始化自己独有的属性
2.该方法内存放的是为对象初始化属性的功能,但是也可以存放其他需要在调用时就执行的代码
3.该方法的返回值只能是none

image

2.4 类中的属性查找

1.数据属性

类中属性查找的顺序是对象先从自己那查找,如果找不到该属性,则去类里面查找。对象修改添加属性和属性值,这并不会影响类里面对应的属性,其余对象获取到的还是原来类里面定义的属性值

类中定义了对象所需要的所有的共有属性和功能,大家访问共有属性和功能的地址都是一样的。
image

2.函数属性

正在调用类中的方法是需要按照:类名.函数名(对象)的方法进行调用,但是这样未免太过麻烦。

所以,类提供了一种绑定方法:对象在调用类中功能(函数)时,会自动把该对象当成参数自动传入。
对象1.类中函数名()==类名.函数名(对象) #这里默认函数名传入了对象1

回顾一下列表、字典,其实也是采用了类的思想!
l=[11,22,33] 等价于 l=list([11,22,33])
其实list就是一个类,l就是一个对象
l.append('dd')等价于list.append(l,'dd') 就是调用list类里的append方法

2.5 类中如何隐藏属性

在属性名前加__前缀,就会实现一个隐藏的效果,外界就不能调用该属性了。

该方法只是语法形式上的变形,通过__dict__查看其真正的语法名,然后在外部也是可以访问到的!

隐藏属性在外部访问不到,但是在类内部还是可以访问到的

这样操作的目的是:不让外部轻易的访问到内部的属性,即使需要访问,也必须需要一些条件。

image

2.6 类中的property

property其实就是一种装饰器,它的功能是把类中的方法伪装成数据属性,调用的时候就不用调用该方法了,直接把方法当成数据调用即可(不用加括号了)。

class ClassName: 
    def __init__(self):
	self.__name = name
    @property #法一:
    def get(self):
        return __self.name

    def set(self,val):
        self.__name = val
    # 法二:伪装的更像了 
    name = property(get,set)
    # 改进:直接在函数上加@name.setter(修改值装饰器)@name.deleter(删除值装饰器),把函数名都改成name
class_obj = ClassName()
# 法一调用,不用加括号了
class_obj.get
# 法二调用
class_obj.name #获取名字
class_obj.name=123 #修改名字

2.7 类中classmethod方法

在类中,我们定义的方法默认是绑定给对象的,即在实例化类的时候,对象会默认当成参数传入到类中的方法里面。
obj = ClassName() #这里obj自动传入了

如何定义一个方法,该方法是默认传入类的呢??
image

只需要在我们需要绑定的方法前面加上@classmethod就行,下次我们在调用该类的方法时会自动传入该类名,调用者是类。

class B:
    @classmethod
    def fun(cls):
        pass

2.8 staticmethod方法

不需要绑定给类或者对象的方法,在对应函数上加上@staticmethod,调用者可以是类或者对象,没有自动传参的效果。

3. 面向对象的三大特性

3.1 封装

封装其实就是整合,对于共有的数据和功能进行整合。

3.2 继承

3.2.1 什么是继承

继承是一种创建新类的方式,新建的类可以称为子类或者派生类,继承的类可以称为父类或者基类

python支持多继承,就是一个新建的类可以继承多个父类,python3默认继承object类,在python2中继承了object的叫新式类,没有继承的叫经典类,python2中需要手动书写需要继承的类,不会默认继承object。

class Student(object): 
    pass

class Student2(object):
    pass
class Sub(Student):# 父类是Student
    pass

class Sub2(Student,Student2): # 父类是Student和Student2
    pass

3.2.2 为什么要用继承

类是用来对象数据和功能冗余的问题,而类是用来解决类与类的冗余

3.2.3 继承中的菱形问题的属性查找(后砖石问题)

菱形问题实际指的是,在python2和python3中菱形模式的继承会导致,继承查找顺序不一致的问题!!,这个需要注意!

image

D类继承了B和C类,B和C类分别继承了A类,如果A中有一个方法,B和C都重写了该方法,而D没有重写,那么D继承的是哪个版本的方法呢?

class A:
    def test(self):
        print('from A')

class B(A):
    def test(self):
        print('from B')

class C(A):
    def test(self):
        print('from C')

class D(B,C): 
    pass
obj = D()
obj.test()
# 查找会从D-->B-->C-->A,如果D的父类顺序换了,则查找顺序也会变成D-->C-->B-->A,python2中的经典类就不一样了,查找顺序为D-->B-->A-->C

其实,对于你定义的每一个类,python都会计算出一个方法解析顺序(MRO)列表,该MRO列表就是一个简单的所有基类的线性顺序列表。

对象.mro()或者类.mro() #查看MRO线性顺序列表

python会在MRO列表中从左到右开始查找基类,知道找到第一个匹配这个属性的类为止,这个MRO列表的构造是通过一个C3线性化算法来实现的(了解一下即可)。

3.2.4 非菱形问题下的查找顺序

image

python2和3的查找顺序为:A-->B--->E--->C--->F--->D---object

3.2.5 多继承下的mixins机制

mixins机制的核心:就是在多继承的背景下尽可能的提升多继承的可读性

python的多继承类中,应当只有一个标识其归属含义的父类,意思是保证多继承的类遵循继承‘is-a’的原则,其余继承的类都应该是mixin类,该类的命名规范一般是以mixin、able、ible为后缀。

mixin类只是用来表达某一类功能的类,并不决定子类的归属,它也不依赖于子类的实现,而且子类也并不是完全依赖mixin类,缺少了该类,子类照常工作,只是缺少了某种功能罢了!!
image

最后,mixin类尽量少用,当mixin类很多的时候,依然会造成可读性差的问题!!

3.2.6 子类派生的新方法中如何重用父类功能

法一:指名道姓的调用某一个类下面的函数,该方法不依赖类的继承


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

class B:
    def __init__(self,name,age,work):
        A.__init__(self,name,age) # 法一:指名道姓
        self.work = work

obj = B('zhang','18','python')
print(obj.__dict__)

法二:super()方法,该方法严格依赖继承关系

调用super()会得到一个特殊的对象,注意该对象是参照当前发起属性查找那个类的mro,去当前类的父类中查找属性!! 辅助下面的列子进行理解!

class A:
    def test(self):
        print('from A')
        super(A, self).test() # python3中super也可以省略括号里的参数

class B:
    def test(self):
        print('from B')

class C(A,B):
    pass

obj = C()
obj.test()
# 1.首先会到obj对象里面去找test方法
# 2.再去C里面找
# 3.再去A里面找test方法,找到了打印
# 4.然后遇到了super()会得到一个特殊的对象,该对象参照当前发起属性查找的类的mro就是C这个类,去当前调用super()方法的父类中查找test属性
# 5.C这个类的mro是[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
# 6.当前super()方法的父类是B
print(C.mro())

3.3 多态与鸭子类型

多态性和鸭子类型的本质在于,不同的类中定义了相同的方法名,这样我们就可以不考虑类而统一用一种方式去使用对象。

比如,所有的类中都定义了read和write方法,那么我们在调用的时候就可以不考虑类,直接让类实例化出来的对象调用read和write方法就行。

标签:__,调用,对象,self,面向对象,class,属性
From: https://www.cnblogs.com/suncolor/p/16603335.html

相关文章

  • 面向对象
    面向过程面向过程程序特点面向过程思想对应的问题:面向过程这种程序设计理念,对应现实生活中某一个点上具体的问题,特别是对应解决问题过程中具体的操作步骤面向过程程......
  • 面向对象的轮播实现
    classRotation{constructor(element){this.banner=element.querySelector('.banner')this.length=this.banner.children.lengthth......
  • 面向对象的回顾以及原型讲解
    面向对象回顾核心概念:万物皆对象(顶层对象Object)抽取行为作为方法抽取名词作为属性俩种构建对象的方式构造函数构建es6的形式classclassPerson{constructor(......
  • 面向对象——内部类
    内部类内部类:在一个类的内部再定义一个类classA{classB{}}A是B的外部类,B是A的内部类。成员内部类packagecom.oop.demo10;publicclassOut......
  • 面向对象——接口
    接口接口最能体现OOP的精髓,对对象的抽象在Java编程语言中是一个抽象类型,是抽象对象的集合,对象通常以interface关键字来声明。普通类:只有具体实现抽象类:具体实现和规......
  • 面向对象——补充:抽象类(目前非重点)
    抽象类(非重点)由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。abstract修饰的类就是抽象类,修饰的方......
  • 面向对象——补充:static
    static静态变量可以直接用类名访问,也称类变量静态变量(或方法)对于类,能被所有对象(实例)共享、publicclassStudent{privatestaticintage;privatedouble......
  • 面向对象(类、对象、属性)
    前言本文主要介绍面向对象中的类、对象以及属性这三个基本概念以及使用方法。一、类class1、什么是类?类是具备共同特征或共同行为的事物的统称。如车类,动物类......
  • 16-java面向对象
    面向对象构造器--快捷键:alt+insert快速生产构造器构造器:和类名相同没有返回值作用:new本质在调用构造方法初始化对象的值注意点:定义有参构造后......
  • 18js面向对象回顾及原型讲解
    面向对象回顾核心概念:万物皆对象(顶层对象Object)抽取名词作为属性抽取行为作为方法俩种构建对象的方式构造函数构建es6的形式classclassPerson{constructor(......