面向对象

Posted accolade

tags:

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

  类,就是一种事物,具有共性。比如dict,人,熊猫

  对象,类的实例化后所产生的,具有个性,比如{1:‘vf’},春哥,团团。

申明类:

class 类名:
    类的文档字符串‘#类的静态属性
  def __init__(self,参数)
    实例化所需要的参数代码
  def 功能

面向对象小结——定义及调用的固定模式

技术图片
class 类名:
    def __init__(self,参数1,参数2):
        self.对象的属性1 = 参数1
        self.对象的属性2 = 参数2

    def 方法名(self):pass

    def 方法名2(self):pass

对象名 = 类名(1,2)  #对象就是实例,代表一个具体的东西
                  #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
                  #括号里传参数,参数不需要传self,其他与init中的形参一一对应
                  #结果返回一个对象
对象名.对象的属性1   #查看对象的属性,直接用 对象名.属性名 即可
对象名.方法名()     #调用类中的方法,直接用 对象名.方法名() 即可
面向对象小结——定义及调用的固定模式

 

 我们定义的类的属性到底存到哪里了?有两种方式查看

dir(类名):查出的是一个名字列表

类名.__dict__:查出的是一个字典,key为属性名,value为属性值

 特殊的类属性

类名.__name__# 类的名字(字符串)

类名.__doc__# 类的文档字符串

类名.__base__# 类的第一个父类(在讲继承时会讲)

类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)

类名.__dict__# 类的字典属性

类名.__module__# 类定义所在的模块

类名.__class__# 实例对应的类(仅新式类中)

class Person:
    country = China
    def __init__(self,name,sex,age,hobby):
        self.name=name
        self.sex=sex
        self.age=age
        self.hobby=hobby
    def func(self):
        print(dir(self))
p1=Person(alex,male,68,study)
print(dir(Person))
print(dir(p1))
print(p1.__dict__)
print(Person.__name__)
print(Person.__doc__)
print(Person.__base__)
print(Person.__bases__)
print(Person.__module__)
print(Person.__class__)
print(Person.__dict__)
#输出的结果为
‘‘‘

[‘__class__‘, ‘__delattr__‘, ‘__dict__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__le__‘, ‘__lt__‘, ‘__module__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘__weakref__‘, ‘country‘, ‘func‘] [‘__class__‘, ‘__delattr__‘, ‘__dict__‘, ‘__dir__‘, ‘__doc__‘, ‘__eq__‘, ‘__format__‘, ‘__ge__‘, ‘__getattribute__‘, ‘__gt__‘, ‘__hash__‘, ‘__init__‘, ‘__le__‘, ‘__lt__‘, ‘__module__‘, ‘__ne__‘, ‘__new__‘, ‘__reduce__‘, ‘__reduce_ex__‘, ‘__repr__‘, ‘__setattr__‘, ‘__sizeof__‘, ‘__str__‘, ‘__subclasshook__‘, ‘__weakref__‘, ‘age‘, ‘country‘, ‘func‘, ‘hobby‘, ‘name‘, ‘sex‘] {‘hobby‘: ‘study‘, ‘sex‘: ‘male‘, ‘name‘: ‘alex‘, ‘age‘: 68} Person None <class ‘object‘> (<class ‘object‘>,) __main__ <class ‘type‘> {‘__init__‘: <function Person.__init__ at 0x0000000000832620>, ‘country‘: ‘China‘, ‘__doc__‘: None, ‘__dict__‘: <attribute ‘__dict__‘ of ‘Person‘ objects>, ‘__module__‘: ‘__main__‘, ‘func‘: <function Person.func at 0x00000000008326A8>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘Person‘ objects>} ‘‘‘

 面向对象的组合

  组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合

 技术图片

 面向对象的命名空间

 

class name_space:
    code=utf-8
    def __init__(self,name,sex,age):
        self.name=name
        self.age=age
        self.sex=sex
lhy=name_space(lhy,female,18)
dxx=name_space(dxx,male,23)
print(name_space.code)#utf-8
print(lhy.code)#utf-8
print(lhy.age)#18
#print(name_space.name)#报错
#name_space.__dict__[‘code‘]=‘unicode‘#报错
name_space.code=unicode
print(name_space.code)#unicode
print(lhy.code)#unicode
lhy.__dict__[code]=gbk
print(lhy.__dict__)#gbk
print(lhy.code)#gbk
print(name_space.code)#unicode
lhy.__dict__.pop(‘code‘)#删除code
print(lhy.code)#unicode
 

 

类的静态变量是可以通过 类.属性名来改变的,但是不可以通过类.__dict__来进行改变。同时静态属性的改变影响对象的静态属性,应为这个属性是绑定在类中并指向一个内存地址的
对象,可也以改变静态属性的。对象名.属性来改变,但是不会影响其他对象以及类的这静态属性的,相当于自己在自己的命名空间开了一新的的空间,不再是绑定关系,删除之后,才会恢复绑定关系

技术图片

再看代码

class group:
     hobby=[eat,drink,swim]
wjw=group
jjs=group
print(group.hobby)#print(group.hobby)
print(wjw.hobby)#print(group.hobby)
print(jjs.hobby)#print(group.hobby)
wjw.hobby.pop()
print(group.hobby)#[‘eat‘, ‘drink‘]
print(wjw.hobby)#[‘eat‘, ‘drink‘]
print(jjs.hobby)#[‘eat‘, ‘drink‘]

 

类里的名字有 类变量(静态属性量)+ 方法名(动态属性)
对象里的名字 对象属性
对象 —— > 类
对象找名字 : 先找自己的 找类的 再找不到就报错
对象修改静态属性的值
对于不可变数据类型来说,类变量最好用类名操作
对于可变数据类型来说,对象名的修改是共享的,重新赋值是独立的

面向对象的三大特征:继承,多态,封装

继承

单继承

父类又称超类,基类
子类又称派生类

class A:
    def fun(self):
        print(A)
        pass
class B:
    def fun(self):
        print(B)
        pass

class A_son(A):
    def fun(self):
        print(A_son(A))
        pass

class AB_son(A,B):
    def fun(self):
        print(AB_son(A,B))
        pass
print(A_son.__bases__)#(<class ‘__main__.A‘>,) 表示A的子类
print(AB_son.__bases__)#(<class ‘__main__.A‘>, <class ‘__main__.B‘>)表示A和B的子类

提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。

继承与抽象:向抽象在继承。

请看代码

class People:
    def eat(self):
        print(%s eat a bread%self.name)
    def sleep(self):
        print(%s is slepping%self.name)
    def look_for_sex(self):
            print(%s is %s % (self.name, self.sex))
class Xiaoming(People):
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex
class Xiaohong(People):
    def __init__(self,name,sex):
        self.name=name
        self.sex=sex
xiaoming=Xiaoming(xiaoming,male)
xiaohong=Xiaohong(xiaohong,female)
xiaoming.eat()#xiaoming eat a bread
xiaohong.look_for_sex()#xiaohong is female

 

注意:此时的父类定义时没有传参数,故可以直接调用

派生

子类也可以添加自己新的属性或者在自己这里重新定义这些属性(不会影响到父类)。

需要注意的是,一旦重新定义了自己的属性且与父类重名,那么调用新增的属性时,就以自己为准了。

技术图片
class A:
    def func(self):
        print(it is father function)
class B(A):
    def func(self):
        print(it is son function)
b= B()
b.func()#it is son function
father_and_son_function

 

技术图片

父类中没有的属性 在子类中出现 叫做派生属性
父类中没有的方法 在子类中出现 叫做派生方法
只要是子类的对象调用,子类中有的名字 一定用子类的,子类中没有才找父类的,如果父类也没有报错
如果父类 子类都有 用子类的

  如果还想用父类的,单独调用父类的:

  父类名.方法名 需要自己传self参数

  super().方法名 不需要自己传self

  在外部调用父类方法是super().方法名 需要自己在(父类名,参数(一般为子类名))

  注意区分内外掉用区别

  super().hahaha() 等价super(B,self).hahaha(),一般用前面的

正常的代码中 单继承 === 减少了代码的重复
继承表达的是一种 子类是父类的关系

关于继承传参数

技术图片
class A:
    def __init__(self,name,sex,age):
        self.name=name
        self.age= age
        self.sex=sex
        print(A传参数完成)
class B(A):
    def __init__(self,name,age,sex,hobby):
        super().__init__(name,age,sex)
        # super(B, self).__init__(name, age, sex)
        #也可以这么写,这样就能统一self
        self.hobby=hobby
        print(hobby传参完成)
a =B(alex,16,male,study)
#结果
#A传参数完成
#hobby传参完成
继承传参

多继承:

多继承中,我们子类的对象调用一个方法,默认是就近原则,找的顺序是什么?
经典类中 深度优先
新式类中 广度优先
python2.7 新式类和经典类共存,新式类要继承object
python3 只有新式类,默认继承object
经典类和新式类还有一个区别 mro方法只在新式类中存在

   类名.mro()  查找多继承的顺序

super 只在python3中存在
super的本质 :不是单纯找父类 而是根据调用者的节点位置的广度优先顺序来的

砖石继承

技术图片

 

 技术图片

技术图片

抽象类与接口类

接口类 : python原生不支持
抽象类 : python原生支持

规范 :接口类或者抽象类都可以
接口类 支持多继承,接口类中的所有的方法都必须不能实现 —— java
抽象类 不支持多继承,抽象类中方法可以有一些代码的实现 —— java

接口类

from abc import ABCMeta,abstractmethod
class start_game(metaclass=ABCMeta):
    @abstractmethod
    def start(self,num):pass
class LOL(start_game):
    def start(self,num):
        print(%s second will be open Lol%num)
class DNF(start_game):
    def start(self,num):
        print(%s second will be open DNF % num)
class QQ(start_game):
    def begin(self,num):
        print(%s second will be open QQ % num)
lol=LOL()
lol.start(5)#5 second will be open Lol
dnf=DNF()
dnf.start(6)#6 second will be open DNF
qq = QQ()
qq.begin(5)#TypeError: Can‘t instantiate abstract class QQ with abstract methods start

 解析

 

 

技术图片

 

 接口内的多继承

from abc import abstractmethod,ABCMeta
class Swim_Animal(metaclass=ABCMeta):
    @abstractmethod
    def swim(self):pass

class Walk_Animal(metaclass=ABCMeta):
    @abstractmethod
    def walk(self):pass

class Fly_Animal(metaclass=ABCMeta):
    @abstractmethod
    def fly(self):pass

class Tiger(Walk_Animal,Swim_Animal):
    def walk(self):
        pass
    def swim(self):
        pass
class OldYing(Fly_Animal,Walk_Animal):pass
class Swan(Swim_Animal,Walk_Animal,Fly_Animal):pass

 

抽象类

 与java一样,python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化

 

为什么要有抽象类

    如果说类是从一堆对象中抽取相同的内容而来的,那么抽象类是从一堆中抽取相同的内容而来的,内容包括数据属性和函数属性。

  比如我们有香蕉的类,有苹果的类,有桃子的类,从这些类抽取相同的内容就是水果这个抽象的类,你吃水果时,要么是吃一个具体的香蕉,要么是吃一个具体的桃子。。。。。。你永远无法吃到一个叫做水果的东西。

    从设计角度去看,如果类是从现实对象抽象而来的,那么抽象类就是基于类抽象而来的。

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

import abc #利用abc模块实现抽象类
class All_file(metaclass=abc.ABCMeta):
    all_type=file
    @abc.abstractmethod #定义抽象方法,无需实现功能
    def read(self):
        子类必须定义读功能
        with open(filaname) as f:
            pass
    @abc.abstractmethod #定义抽象方法,无需实现功能
    def write(self):
        子类必须定义写功能
        pass
class Txt(All_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print(文本数据的读取方法)
    def write(self):
        print(文本数据的读取方法)
class Sata(All_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print(硬盘数据的读取方法)
    def write(self):
        print(硬盘数据的读取方法)
class Process(All_file): #子类继承抽象类,但是必须定义read和write方法
    def read(self):
        print(进程数据的读取方法)
    def write(self):
        print(进程数据的读取方法)
wenbenwenjian=Txt()
yingpanwenjian=Sata()
jinchengwenjian=Process()
#这样大家都是被归一化了,也就是一切皆文件的思想
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read()
print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)
#输出结果

#文本数据的读取方法
#硬盘数据的读取方法
#进程数据的读取方法
#file
#file
#file

 

 



 

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

面向面试编程代码片段之GC

PHP面向对象之选择工厂和更新工厂

Java中面向对象的三大特性之封装

python之路之前没搞明白4面向对象(封装)

Scala的面向对象与函数编程

Python面向对象学习之八,装饰器