Python面向对象编程(一)

一、面向对象编程

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}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,258评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,335评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,225评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,126评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,140评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,098评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,018评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,857评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,298评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,518评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,400评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,993评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,638评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,661评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容