面向对象编程

类和对象

1.什么叫类: 类是一种数据结构, 就比如一个模型, 该模型用来表述一类事务(事务即数据和动做的结合体), 用它来生产真实的物体(实例).python

2.什么叫对象: 睁开眼, 你看到的一切的事物都是一个个的对象, 你能够把对象理解为一个具体的事物(事物即数据和动做的结合体)算法

3.类与对象的关系: 对象都是由类产生的编程

4.什么叫实例化:由类生产对象的过程叫实例化,类实例化的结果就是一个对象,或者叫作一个实例(实例=对象)数据结构

面向对象设计与面向对象编程

面向对象设计:将一类具体事物的数据和动做整合到一块儿,即面向对象设计socket

#用基于结构化的语言来实现面向对象设计
def wang(name,genle,type):
    def jiao(dog):
        print("%s正在叫"%dog["name"])
    def chi(dog):
        print("%s正在吃"%dog["name"])
    def init(name,genle,type):
        dog1 ={
            "name":name,
            "genle":genle,
            "type":type,
            "jiaoa":jiao,
            "chi":chi
        }
        return dog1
    return init(name,genle,type)

d1 = wang("xiaoming","gong","tianyuanquan")
print(d1)
d1["jiaoa"](d1)

面向对象编程: 用定义类 + 实例/对象的方式去实现面向对象的设计函数

class Chinese:
    name = "abc"
    def chifan(self,x):
        print("姓名:%s喜欢吃%s"%(self.mingzi,x))
    def shuijiao(self):
        print("nianling:%s"%self.nianling)
    def __init__(self,name,age):
        self.mingzi = name
        self.nianling = age
f1 = Chinese("xiaoming",18)
f1.chifan("eat")
f1.shuijiao()

类的声明

1 大前提:
 2 1.只有在python2中才分新式类和经典类,python3中统一都是新式类
 3 2.新式类和经典类声明的最大不一样在于,全部新式类必须继承至少一个父类
 4 3.全部类甭管是否显式声明父类,都有一个默认继承object父类(讲继承时会讲,先记住)
 5 在python2中的区分
 6 经典类:
 7 class 类名:
 8     pass
 9 
10 经典类:
11 class 类名(父类):
12     pass
13 
14 在python3中,上述两种定义方式全都是新式类


python3中声明类
1 '''
 2 class 类名:
 3     '类的文档字符串'
 4     类体
 5 '''
 6 
 7 #咱们建立一个类
 8 class Data:
 9     pass
10 
11 #用类Data实例化出一个对象d1
12 d1=Data()

类的属性

类有数据属性跟函数属性(又称方法属性)ui

class Chinese:
    name = "abc"
    def chifan(self,x):
        print("姓名:%s喜欢吃%s"%(self.mingzi,x))
    def shuijiao(self):
        print("nianling:%s"%self.nianling)
    def __init__(self,name,age):#为实例定制数据属性,可使用类的一个内置方法__init__()该方法,在类()实例化是会自动执行
        self.mingzi = name
        self.nianling = age
f1 = Chinese("alex",18)   #类的实例化,至关于运行__init__函数,将参数传给__init函数体中对应的位置,生成一个字典,其中self即表明f1自身
f1.chifan("eat")#经过.调用类的属性,首先会在__init__做用域内查找,若没找到会到类的属性中寻找,实例化生成的对象只具有数据属性,调用的方法为类的属性并不是生成的对象所具有的属性
f1.shuijiao()

  有两种方法查看类的属性spa

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

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

1 class Chinese:
2     name = "abc"
3     def chifan(self):
4         print(123)
5     def shuijiao(self):
6         print("456")
7 print(Chinese.name)#打印的是name属性对应的内容
8 print(Chinese.__dict__)#显示结果是一个字典,包含类的全部属性:属性值 
9 print(dir(Chinese))#显示结果是一个列表,包含类(包含内建属性在内的)全部的属性名

  特殊的类属性

  __name__,类的名字

  __doc__,查看类的文档字符串

  __module__, 类定义所在的模块__class__, 实例C对应的类(仅新式类中)

  类的方法属性的增删改查

 

 1 class math:
 2     country = "China"
 3     def chi(self,food):
 4         print("%s正在吃%s"%(self.mingzi,food))
 5     def __init__(self,name):
 6         self.mingzi = name
 7 f1 = math("alex")
 8 print(math.country)    #查看
 9 # print(dir(math))
10 # print(math.__dict__)
11 def yundong(self,hobby):#增长
12     print("%s正在%s"%(self.mingzi,hobby))
13 math.aihao = yundong
14 #print(math.__dict__)
15 f1.aihao("打篮球")
16 #del math.chi
17 #print(math.__dict__)
18 def aichi(self,food):#修改
19     print("%s很开心的吃%s"%(self.mingzi,food))
20 math.chi =aichi
21 f1.chi("")

 

类的数据属性的增删改查

 1 class math:
 2     country = "China"
 3     def chi(self,food):
 4         print("%s正在吃%s"%(self.mingzi,food))
 5     def __init__(self,name,age):
 6         self.mingzi = name
 7         self.nianling = age
 8 
 9 f1 = math("xiaoming",18)
10 print(f1.__dict__)   #查看
11 f1.mingzi = "eric" #修改
12 print(f1.__dict__)
13 f1.xingbie = ""  # 增长
14 del f1.mingzi    #删除
15 print(f1.__dict__

类属性与对象(实例)属性

  1.实例化会自动触发__init__函数的运行,最后返回一个值即实例, 咱们要找的实例属性就存放            在 __init__函数的局部做用域里

  2.类有类的属性字典, 就是类的做用域, 实例有实例的属性字典, 即实例的做用域

  3.综上, 一个点表明一层做用域, obj.x先从本身的做用域找, 本身找不到去外层的类的字典中去         找, 都找不到, 就会报错

  4.在类中没有使用点的调用, 表明调用全局变量

1 country = "China"
2 class Chinese:
3     country = "japan"
4     def __init__(self,name):
5         self.mingzi = name
6         print(country)#打印的是普通变量country,非类结构中的变量,要调用类中的变量要用"."调用
7 f1 = Chinese("tom")

静态属性,类方法,静态方法

 1 class Room:
 2     arg = 123
 3     def __init__(self,name,weith,lenth,height):
 4         self.mingzi = name
 5         self.kuandu = weith
 6         self.changdu = lenth
 7         self.gaodu = height
 8     @property#静态属性,将实例化对象变成类的数据属性,将该方法封装起来,做用可隐藏逻辑代码,直接用实例+"."调用该方法
 9     def tiji(self):
10         return self.kuandu*self.changdu*self.gaodu
11 
12     @classmethod#类方法,专门供类使用,与实例无关,类方法只能访问类相关的属性,不能访问实例属性,与实例无关
13     def tell_info(cls,x):#默认参数cls不可变,为类名,后边可接参数
14         print(cls)
15         print("------>",Room.arg,x)
16 
17     @staticmethod   #静态方法 ,类的静态方法,没有默认参数,不能使用类变量和实例变量
18     def op(x,y,z):
19         print(x,y,z)
20 f1 = Room("tom",10,50,20)
21 print(f1.tiji)#因为用了property方法封装该方法(已变成数据属性),故可直接调用该数据属性
22 Room.tell_info("abc")
23 Room.op(1,2,3)     #类传参数能够调用
24 f1.op(1,2,3)      #实例传参数能够调用

组合

做用:   作关联

 1 class School:
 2     def __init__(self,name,difang):
 3         self.name = name
 4         self.difang = difang
 5 class Teacher:
 6     def __init__(self,name,sex,school):
 7         self.name = name
 8         self.sex = sex
 9         self.school = school
10 class Lesson:
11     def __init__(self,name,price,period,techer):
12         self.name = name
13         self.price = price
14         self.period = period
15         self.techer = techer
16 
17 p1 = School("baidu","北京")
18 t1 = Teacher("tom","male",p1)#将p1对象直接添加到t1对象属性中
19 L1 = Lesson("python班",10000,"4month",t1)

面向对象编程三大特性

(1)类的继承: 类的继承跟现实生活中的父,子,孙,重孙,继承关系同样,父类又称为基类

    python中类的继承分为:  单继承和多继承

class ParentClass1:
    pass

class ParentClass2:
    pass

class SubClass(ParentClass1): #单继承
    pass

class SubClass(ParentClass1,ParentClass2): #多继承
    pass

   子类继承了基类的全部属性

class Dad:
    money = 10
    def __init__(self,name):
        self.name = name
    def hit_son(self):
        print("打人")
class Son(Dad):#继承参数“类”的全部属性
    money = 5000#当子级类属性跟父级类属性重名时,调用当级类方法会先从当级寻找,找不到会去父级找
    pass
p1 = Son("eric")
print(p1.name)
p1.hit_son()
print(p1.money)

  当类之间有显著的不一样,  而且较小的类是较大的类所须要的组件时,  用组合比较好

  当类之间有不少相同的功能,  提取这些共同的功能作成基类,  用继承比较好

继承同时具备两种含义

  含义一:继承基类的方法,  而且作出本身的改变或者扩展  (代码重用)

  含义二:声明某个子类兼容于某基类, 定义一个接口类, 子类继承接口类,  而且实现接口中定                     义的方法

接口继承
import abc   #调用接口继承模块

class All_file(metaclass=abc.ABCMeta):#声明某个子类兼容于某基类,定义一个接口类,子类继承接口类,而且实现接口中定义的方法
    @abc.abstractclassmethod   #装饰器使方法具有接口继承特性
    def read(self):
        pass
    @abc.abstractclassmethod
    def write(self):
        pass

class Disk(All_file):#子类继承基类时,必须对基类的方法进行派生才可实例化
    def read(self):
        print("disk-read")
    def write(self):
        print("disk-write")
class Cd(All_file):
    def read(self):
        print("cd-read")
    def write(self):
        print("cd-write")
class Mem(All_file):
    def read(self):
        print("mem-read")
    def write(self):
        print("mem-write")
p1 = Disk()
p1.read()

继承顺序: python若是继承了多个类, 遵循深度优先跟广度优先顺序

当类是经典类时,  多继承状况下,  会按照深度优先方式查找

当类是新式类时,  多继承状况下,  会按照广度优先方式查找

经典类与新式类的差异:  新式类在定义时便自动继承了object类,  而经典类没有

新式类继承顺序: 对于你定义的每个类, python会计算出一个方法解析顺序(MRO)列表,这个MRO列表就是一个简单的全部基类的线性顺序列表

为了实现继承,python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止

而这个MRO列表的构造是经过一个C3线性化算法来实现的. 咱们不去深究这个算法的数学原理, 它实际上就是合并全部的MRO列表并遵循以下三条准则:

1.子类会先于父类被检查

2.多个父类会根据它们在列表中的顺序被检查

3.若是对下一个类存在两个合法的选择,选择第一个父类

 1 继承顺序
 2 
 3 
 4 class A:
 5     def test(self):
 6         print("testA")
 7 class B(A):
 8     def test(self):
 9         print("testB")
10 class C(A):
11     def test(self):
12         print("testC")
13 class D(B):
14     def test(self):
15         print("testD")
16 class E(C):
17     def test(self):
18         print("testE")
19 class F(D,E):
20     def test(self):
21         print("testF")
22 f1 = F()
23 print(F.__mro__)#(<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
24 f1.test()#实例调用方法时,遵循mro顺序,会优先从子级寻找,找不到往上,先广度优先,若还找不到会找最深一级,若尚未会报错

子类中调用父类方法

 1 class jiaotong:
 2     def __init__(self,name,speed):
 3         self.name = name
 4         self.speed = speed
 5     def run(self):
 6         print("%srunning!"%self.name)
 7 class bicycle(jiaotong):
 8     def __init__(self,name,speed,type):
 9         #jiaotong.__init__(self,name,speed)#第一种方法:类调用,子级继承父级,能够在调用父级方法的基础上进行派生,减小重复代码
10         super().__init__(name,speed)#第二种方法:用内置super().调用父级方法
11         self.type = type
12     def run(self):
13         jiaotong.run(self)
14         print("%s开动了"%self.name)
15 
16 
17 f1 = bicycle("danche",10,"meilida")
18 print(f1.name,f1.speed,f1.type)
19 f1.run()

多态,封装

  多态:调用不一样的子类将会产生不一样的行为,多态是在继承上实现的

 1 class Dt:
 2     def __init__(self,name,temputer):
 3         self.name = name
 4         self.temputer = temputer
 5     def fu(self):
 6         if self.temputer < 0:
 7             print("【%s】温度过低变成冰了!"%self.name)
 8         elif self.temputer > 0 and self.temputer < 100:
 9             print("【%s】变成水了!"%self.name)
10         elif self.temputer > 100:
11             print("【%s】温度过高变成蒸汽了!"%self.name)
12 w1 = Dt("water",-2)
13 ice = Dt("ice",5)
14 steam = Dt("steam",150)
15 w1.fu()
16 ice.fu()
17 steam.fu()

  封装的概念就是隐藏

  第一层面的封装: 类就是麻袋, 这自己就是一种封装

  第二个层面的封装:类中定义私有的, 只在类的内部使用,外部没法访问, 类中定义属性名时在其前面加上_或者__可实现该属性的隐藏,但这种隐藏只是一种语言上的约定,python并不会从底层禁止你访问

class People:
    _population = "60亿"
    __star = "earth"
    def __init__(self,name,salary):
        self.name = name
        self.slary = salary
p1 = People("tom",1000)
print(p1._population)#对于第一种用_封装的属性,虽然是私有的,但仍然能够访问

print(p1._People__star)#对于第二种用__封装的属性,在其前面加上_类名仍然能够访问

  python并不会真的阻止你访问私有属性, 模块也遵循这种预约, 若是模块名以单下划线开头, 那         么from module import *时不能导入,可是你from module import _private_module依然是能够导         入的

  其实不少时候你去调用一个模块的功能时会遇到单下划线开头的

  (socket._socket,sys._home,sys._clear_type_cache),这些都是私有的, 原则上是供内部调用的,

  但经过特殊方法依然能够调用

  注意 : 双下划线开头的属性在继承给子类时, 子类是没法覆盖的(原理也是基于python自动作了

  双下划线开头的名字的重命名工做)

相关文章
相关标签/搜索