Python面向对象编程(一)

2018-06-27  本文已影响0人  itxone

一、面向对象编程

1. 面向对象编程和面向过程编程的区别

  • 面向过程编程:机械思维,简化复杂的流程,可扩展性差
  • 面向对象编程:上帝思维,编程复杂度高于面向过程,可扩展性强

2. 什么是面向对象编程

  • 对象是特征和技能的结合体
  • 创造对象,给对象赋予特征和技能,让对象干活
  • 修改一个对象,对其他地方不影响
  • 面向对象编程,主要解决的是可扩展性

3. 类

  • 类由对象组成,是一系列对象的结合体,这些对象具有相似的特征和技能
  • 在面向对象编程中,站的角度不同,分的类不同
  • 在现实世界中现有具体的对象,才有分类
  • 但是在程序中,必须先定义类,后调用类,来产生对象

① 定义类

  • 定义类的语法:class 类的名字:,类的名字使用驼峰语法
    类的名字,就是类中名字的容器

类的作用:

  • 类当做容器,存放类里面的名字
  • 调用类,就会产生对象
class OldboyStudent:
    school='oldboy'

    def choose_course(self):
        print('is choosing course')

    print('=========')
================================执行结果如下======================================
=========

说明:类体代码在类定义阶段就会执行,并产生一个类的名称空间

② 查看类的名称空间

  • 类的名字.__dict__
class OldboyStudent:
    school='oldboy'

    def choose_course(self):
        print('is choosing course')

print(OldboyStudent.__dict__)
================================执行结果如下======================================
{'__module__': '__main__', 'school': 'oldboy', 'choose_course': <function OldboyStudent.choose_course at 0x0000029B42F7D158>, '__dict__': <attribute '__dict__' of 'OldboyStudent' objects>, '__weakref__': <attribute '__weakref__' of 'OldboyStudent' objects>, '__doc__': None}

② 取出类的名称空间的内容

class OldboyStudent:
    school='oldboy'

    def choose_course(self):
        print('is choosing course')
# 取出类的名称空间的内容
print(OldboyStudent.__dict__['school'])
print(OldboyStudent.__dict__['choose_course'])
OldboyStudent.__dict__['choose_course']('需要写内容') # 调用类中的函数,但是要加函数self
================================执行结果如下======================================
oldboy
<function OldboyStudent.choose_course at 0x000001923570D158>
is choosing course

③ 增加查类名称空间的内容

class OldboyStudent:
    school='oldboy'

    def choose_course(self):
        print('is choosing course')

OldboyStudent.country='China' # 相当于OldboyStudent.__dict__['country']='China'
print(OldboyStudent.__dict__)
image.png

③ 修改类名称空间的内容

class OldboyStudent:
    school='oldboy'

    def choose_course(self):
        print('is choosing course')

OldboyStudent.country='CHINA'
print(OldboyStudent.__dict__)
image.png

④ 删除类名称空间的内容

class OldboyStudent:
    school='oldboy'

    def choose_course(self):
        print('is choosing course')

del OldboyStudent.school  # 删除

print(OldboyStudent.__dict__)

⑤ 调用类

  • 语法格式:类的名字(),调用类就是产生对象
  • 调用类的过程,又称类的实例化,实例化的结果成为类的对象或类的实例
  • 调用类会获得一个返回值,这个返回值就是类的对象(实例)

4. 类的属性

  • 先在现实世界中总结对象(根据特征和技能),得到现实世界中的类,再定义为程序中的类,调用类,产生程序中的对象(公共类和独有对象)
# 定义类
class OldboyStudent:
    # 特征
    school='oldboy'

    # 技能
    def choose_course(self):
        print('is choosing course')

# 类属性的查看类
print(OldboyStudent.school)  # OldboyStudent.__dict__['school']
# 类属性的增加(没有的名字)
OldboyStudent.x=1  # OldboyStudent.__dict__['x']=1
# 类属性的修改(已有的名字)
OldboyStudent.school='Oldboy'
# 类属性的删除
del OldboyStudent.x
  • OldboyStudent.a 点后面的名字a称为属性,表示在类的名称空间中找到属性的值
    变量和函数组成,变量是数据,函数是功能
  • 类中定义的函数,是类的函数属性
  • 类中定义的变量,是类的数据属性
class OldboyStudent:
    # 特征
    school='oldboy'

    # 技能
    def choose_course(self):
        print('is choosing course')

# 类用来生产对象,类调用几次就生产几次
stu1=OldboyStudent()
stu2=OldboyStudent()
stu3=OldboyStudent()
print(stu1)
print(stu2)
print(stu3)
==============================执行结果如下===================================
<__main__.OldboyStudent object at 0x000002574C24BDA0>
<__main__.OldboyStudent object at 0x000002574C24BE10>
<__main__.OldboyStudent object at 0x000002574C24BDD8>

# 类产生的对象,这个对象可访问类中的属性,比如:
# 对象访问类的属性和类访问属性语法一样
print(OldboyStudent.school)
print(stu1.school)   # 作用同上
==============================执行结果如下===================================
oldboy
oldboy
class OldboyStudent:
    school='oldboy'
    def choose_course(self):
        print('is choosing course')

# 生产对象
stu1=OldboyStudent()
stu1.name='itxone'
stu1.age=18
stu1.sex='male'
print(stu1.name,stu1.age,stu1.sex)
==============================执行结果如下===================================
itxone 18 male

5. 为对象定义独有的属性

  • 对象本身也是名称空间,即存放自己独有的名字的容器,因此,增加对象的属性,就是在对象的名称空间中增加名字
  • 而类中存放的是对象共有的属性(数据属性和函数属性)

① 查看对象的名称空间,默认是空的字典

class OldboyStudent:
    school='oldboy'
    def choose_course(self):
        print('is choosing course')

stu1=OldboyStudent()
print(stu1.__dict__)
==============================执行结果如下===================================
{}
class OldboyStudent:
    school='oldboy'
    def choose_course(self):
        print('is choosing course')

stu1=OldboyStudent()
# 添加属性
stu1.name='itxone'
stu1.age=18
stu1.sex='male'
print(stu1.__dict__)
==============================执行结果如下===================================
{'name': 'itxone', 'age': 18, 'sex': 'male'}

② 当许多对象都要传入重复的name age sex属性时,就可以将功能,定义到类中

  • 添加__init__方法,表示在调用类时,会自动触发该功能
class OldboyStudent:
    school='oldboy'
    # 对象在造出来的时候,就带有对象的独有属性
    def __init__(obj,x,y,z):
        obj.name=x
        obj.age=y
        obj.sex=z

    def choose_course(self):
        print('is choosing course')

stu1=OldboyStudent('itxone',18,'male')
print(stu1.__dict__)
==============================执行结果如下===================================
{'name': 'itxone', 'age': 18, 'sex': 'male'}

调用类时发生两件事:

  • 先创建一个空对象stu1
  • 然后自动触发类中的__init__功能,将对象stu1和括号内的参数一起传入

属性查找

  • 对象属性查找顺序:先从对象自己的名称空间找,再从类的名称空间中找,如果都没有就报错
  • def __init__(self,x,y,z):中的self是约定俗成写法,表示传的是对象自己

统计生产了多少次对象

class OldboyStudent:
    school='oldboy'
    count=0   # 类中名称空间的名字
    def __init__(self,x,y,z):
        self.name=x
        self.age=y
        self.sex=z
        OldboyStudent.count+=1 # 调用了类中名称空间的名字,类中的属性变了,所有的都变了(类的属性共享)

    def choose_course(self):
        print('is choosing course')
        
# 生产对象
stu1=OldboyStudent('itxone',18,'male')
stu2=OldboyStudent('itxone',18,'male')
stu3=OldboyStudent('itxone',18,'male')
print(OldboyStudent.count)
print(stu1.count)
print(stu2.count)
print(stu3.count)
==============================执行结果如下===================================
3
3
3
3

6. 绑定方法

  • 类名称空间中,定义的数据属性和函数属性,都是共享给所有对象使用的,类中函数大多是绑定给对象用的
  • 对象名称空间中,定义的只有数据属性,而且是对象独有的数据属性

① 类访问类中函数和对象访问类中的函数的区别

  • 类中定义的函数属性,类使用这个函数属性,就当做普通函数使用,遵循函数的参数规则
  • 而对象使用类中的函数,是绑定给对象用的
  • 绑定的效果:绑定给哪个对象,就由哪个对象调用,并且将这个绑定对象作为函数的第一个参数自动传入
  • 不同的对象,可以重复使用类中的函数,即函数的功能
class OldboyStudent:
    school='oldboy'
    count=0

    def __init__(self,x,y,z):
        self.name=x
        self.age=y
        self.sex=z
        OldboyStudent.count+=1

    def choose_course(self):  # self就是绑定的对象,自动传入
        print('%s is choosing course' %self.name)

stu1=OldboyStudent('itxone',18,'male')
stu1.choose_course()
print(stu1)
print(stu1.choose_course)
==============================执行结果如下===================================
itxone is choosing course
<__main__.OldboyStudent object at 0x0000028F1966BE10>
<bound method OldboyStudent.choose_course of <__main__.OldboyStudent object at 0x0000028F1966BE10>>  # 绑定方法

说明:类汇总定义的函数,类可以使用,但是,类定义的函数大多数情况下都是绑定对对象用的,因此,类中定义的函数都自带self参数,表示自动传入绑定的对象

② 使用绑定方法的优点:

  • 使用绑定方法,不用再重复输入相似的代码,减少了代码量,节省内存空间
  • 对象的技能就是绑定方法,通过对象传入对象全部数据(传对象的名称空间,比如姓名,年龄等可以一起传),使类中的函数可以使用这个对象的所有数据
  • 因此,给一个对象,给的是对象的所有数据和处理这些数据的绑定方法
class Foo:
    pass

obj=Foo() # 创造一个对象
print(obj)
==============================执行结果如下===================================
<__main__.Foo object at 0x0000013EAF70A5F8>

③ 自定义的绑定方法和内置的绑定方法

  • Python3中统一了类与类型的概念,类就是类型,类型就是类
# 自定义的绑定方法
class Foo: # 定义的一个类
    def func(self,x):  # 类中的函数
        pass

obj=Foo()  # Foo()类,创造了一个obj的对象
obj.func(1) # obj.func是绑定方法 相当于Foo.func(obj,1)

# 内置的绑定方法(以下为伪代码)
class list: # list是定义的一个类
    def append(self,x): # append的就是类中的函数
        pass

lb=[1,2,3] # 相当于lb=list([1,2,3])
lb.append(123) # 绑定方法,相当于list.append(lb,123)

小结

  • 对象是一个高度整合的产物,整合了数据和专门操作该数据的方法(绑定方法)
class Foo:
    def __init__(self,host,port,db,charset):
        self.host=host
        self.port=port
        self.db=db
        self.charset=charset
        
    def excl(self,sql):
        conn= connect(self.host,self.port,self.db,self.charset)
        conn.execute(sql)
        return xxx
# 生产一个对象,传入固定的参数
obj1=Foo('1.1.1.1',3306,'db1','utf-8')
# 绑定方法只需要传入一个参数就可以,不用重复传'1.1.1.1',3306,'db1','utf-8'
obj1.excl('select * from t1')
obj1.excl('select * from t2')
obj1.excl('select * from t3')

# 如果传入固定的参数有变动,在产生一个对象即可,节省了很多代码
obj2=Foo('10.10.10.10',3307,'db1','utf-8')
obj2.excl('select * from t4')
obj2.excl('select * from t5')

面向对象的特性之一:继承和派生

1. 什么是继承

  • 继承是一种新建类的方式,新建的类称为子类,被继承的类称为父类
  • 子类会具备父类的属性,子类可以使用父类的功能
  • 注意:继承是类与类之间的关系

2. 为什么要有继承

  • 继承的优点:可以减少代码的冗余

3. 如何用继承

  • 定义子类的语法:class 子类名(父类名)
  • 在Python中,支持一个类同时继承多个父类
# 父类
class Parent1:
    pass

# 子类
class Sub(Parent1)
    pass

# 查看子类继承关系
print(Sub1.__bases__)
==============================执行结果如下===================================
(<class '__main__.Parent1'>,)

① Python3和Python2中继承的区别

  • 在Python3中,如果一个类没有继承任何类,默认继承object
  • 在Python2中,如果一个类没有继承任何类,默认不会继承object
  • 新式类:只要是继承了object的类以及该类的子类,都是新式类
  • 经典类:没有继承object的类以及该类的子类,都是经典类
  • 在Python3中都是新式类,只有Python2中才区别新式类与经典类

② 继承多个父类

class Parent1:
    pass

class Parent2:
    pass

class Sub1(Parent1,Parent2):
    pass

print(Sub1.__bases__)
==============================执行结果如下===================================
(<class '__main__.Parent1'>, <class '__main__.Parent2'>)

4. 寻找继承关系的流程

  • 找对象的相似之处,就可以总结出类,找类相似之处,就可以总结出父类
  • 对象查找属性的顺序:对象自己--->对象的类--->父类--->父类......
class Foo:
    def f1(self):
        print('Foo.f1')

    def f2(self):
        print('Foo.f2')
        self.f1()

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

obj=Bar()
obj.f2()
==============================执行结果如下===================================
Foo.f2
Bar.f1

5. 子类派生

  • 派生:子类中新定义的属性(技能),子类在使用时,始终以自己的为准

① 未使用派生

  • 未使用派生和继承,代码冗余过多
class OldboyStudent():
    school = 'oldboy'
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

    def choose_course(self):
        print('%s is choosing course' %self.name)

class OldboyTeacher():
    school = 'oldboy'
    def __init__(self,name,age,sex,level):
        self.name=name
        self.age=age
        self.sex=sex
        self.level=level
    def score(self):
        print('%s in scoring' %self.name)

stu1=OldboyStudent('xut',18,'male')
tea1=OldboyTeacher('xdw',18,'male',10)

stu1.choose_course()
tea1.score()
==============================执行结果如下===================================
xut is choosing course
xdw in scoring

② 使用派生方式一

  • 在子类派生出新功能中,重用父类功能方式:指定道姓访问一个类的函数,该方式与继承无关
  • 不推荐使用这种派生,如果套的太多就,是强耦合的过程
# 总结出共点,分出类
class OldboyPeople:
    school='oldboy'
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

class OldboyStudent(OldboyPeople):
    def choose_course(self):
        print('%s is choosing course' %self.name)

class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level):
        # self.name=name
        # self.age=age
        # self.sex=sex
        # 派生出新的功能,指定道姓访问一个类的函数
        OldboyPeople.__init__(self,name,age,sex)
        self.level=level
    def score(self):
        print('%s in scoring' %self.name)

stu1=OldboyStudent('xut',18,'male')
tea1=OldboyTeacher('xdw',18,'male',10)
print(stu1.__dict__)
print(tea1.__dict__)
==============================执行结果如下===================================
{'name': 'xut', 'age': 18, 'sex': 'male'}
{'name': 'xdw', 'age': 18, 'sex': 'male', 'level': 10}

③ 子类派生出来的功能,不一定和父类有直接关系

# 总结出共点,分出类
class OldboyPeople:
    school='oldboy'
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex

class OldboyStudent(OldboyPeople):
    def choose_course(self):
        print('%s is choosing course' %self.name)

class OldboyTeacher(OldboyPeople):
    def __init__(self,name,age,sex,level):
        # self.name=name
        # self.age=age
        # self.sex=sex
        OldboyPeople.__init__(self,name,age,sex)
        self.level=level
    # 派生打分功能,和父类没有直接关系
    def score(self,stu_obj,num):
        print('%s in scoring' %self.name)
        stu_obj.score=num

stu1=OldboyStudent('xut',18,'male')
tea1=OldboyTeacher('xdw',18,'male',10)

tea1.score(stu1,99)
print(stu1.__dict__)
==============================执行结果如下===================================
xdw in scoring
{'name': 'xut', 'age': 18, 'sex': 'male', 'score': 99}
上一篇下一篇

猜你喜欢

热点阅读