博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
面向对象编程(基础)
阅读量:4878 次
发布时间:2019-06-11

本文共 8658 字,大约阅读时间需要 28 分钟。

目录

面向对象编程

面向对象编程的核心是对象二字,对象是特征与技能的结合体。

基于面向对象编程的思想编写程序,就好比是在创造一个世界,你就是这个世界的上帝,是一种上帝式的思维方式。

优点:可扩展型强

缺点:编程的复杂度要高于面向过程

类与对象

对象是特征与技能的结合体,类就是一系列对象相似的特征与技能的结合体。

现实世界中,先有一个个具体存在的对象,随着发展才有了分类的概念,Python程序中也有类这个概念,但是Python程序中必须先定义类,然后调用类来产生对象。

现实世界中定义类和对象

定义对象

  • 学生类:

    相似的特征:

    学校 = '北京大学'

    相似的技能:

    选课

程序中定义类和对象

定义类

# 注意类中定义变量使用驼峰体class BeijingStudent():    school = 'peking'    def choose_course(self):        print('is choosing course')

定义函数时,函数只检测语法,不执行代码。但是定义类的时候,类体代码会在类定义阶段就立刻执行,并且会产生一个类的名称空间,也就是说类的本身其实就是一个容器/名称空间,是用来存放名字的,这是类的用途之一。

print(BeijingStudent.__dict__)
{'__module__': '__main__', 'school': 'peking', 'choose_course': 
, '__dict__':
, '__weakref__':
, '__doc__': None}
print(BeijingStudent.__dict__['school'])
peking
print(BeijingStudent.__dict__['choose_course'])
try:    BeijingStudent.__dict__['choose_course']()except Exception as e:    print('error:', e)
error: choose_course() missing 1 required positional argument: 'self'
print(BeijingStudent.school)
peking
BeijingStudent.choose_course(111)
is choosing course
print(BeijingStudent.choose_course)
BeijingStudent.__dict__['choose_course']
BeijingStudent.country = 'China'
BeijingStudent.__dict__['country']
'China'
BeijingStudent.country = 'CHINA'
BeijingStudent.__dict__['country']
'CHINA'
del BeijingStudent.school
print(BeijingStudent.__dict__)
{'__module__': '__main__', 'choose_course': 
, '__dict__':
, '__weakref__':
, '__doc__': None, 'country': 'CHINA'}

定义对象

调用类即可产生对象,调用类的过程,又称为类的实例化,实例化的结果称为类的对象/实例。

stu1 = BeijingStudent()  # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例print(stu1.country)
CHINA
stu2 = BeijingStudent()  # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例print(stu2.country)
CHINA
stu3 = BeijingStudent()  # 调用类会得到一个返回值,该返回值就是类的一个具体存在的对象/实例stu3.choose_course()
is choosing course

定制对象独有特征

类中定义的函数是类的函数属性,类可以使用,但使用的就是一个普通的函数而已,意味着需要完全遵循函数的参数规则,该传几个值就传几个。

引入

class BeijingStudent:    school = 'peking'    def choose_course(self):        print('is choosing course')stu1 = BeijingStudent()stu2 = BeijingStudent()stu3 = BeijingStudent()

对于上述的学生类,如果类的属性改了,则其他对象的属性也会随之改变。

print(stu1.school)BeijingStudent.school = 'PEKING'
peking
print(stu1.school)
PEKING

定制对象独有特征

print(stu1.__dict__)
{}
print(stu2.__dict__)
{}

对象本质类似于类,也是一个名称空间,但是对象的名称空间存放对象独有的名字,而类中存放的是对象们共有的名字。因此我们可以直接为对象单独定制名字。

stu1.name = 'tom'stu1.age = 18stu1.gender = 'male'print(stu1.name, stu1.age, stu1.gender)
tom 18 male
try:    print(stu2.name, stu2.age, stu2.gender)except Exception as e:    print(e)
'BeijingStudent' object has no attribute 'name'
stu2.name = 'jerry'stu2.age = 18stu2.gender = 'female'print(stu2.name, stu2.age, stu2.gender)
jerry 18 female

类定义阶段定制属性

def init(obj, x, y, z):    obj.name = x    obj.age = y    obj.gender = zinit(stu1, 'tom1', 19, 'male1')print(stu1.name, stu1.age, stu1.gender)
tom1 19 male1
init(stu2, 'jerry1', 29, 'female1')print(stu2.name, stu2.age, stu2.gender)
jerry1 29 female1

使用上述方法虽然让我们定制属性更简单,但还是太麻烦了,如果可以在实例化对象的时候自动触发定时属性,那就更方便了,因此可以使用类的__init__方法。

class BeijingStudent:    school = 'peking'    def __init__(self, name, age, gender):        '''调用类时自动触发'''        self.name = name        self.age = age        self.gender = gender        print('*'*20)    def choose_course(self):        print('is choosing course')try:    stu1 = BeijingStudent()except Exception as e:    print(e)
__init__() missing 3 required positional arguments: 'name', 'age', and 'gender'
stu1 = BeijingStudent('tom', 18, 'male')
********************
  • 通过上述现象可以发现,调用类时发生两件事:
    • 创造一个空对象
    • 自动触发类中__init__功能的执行,将stu1以及调用类括号内的参数一同传入
print(stu1.__dict__)
{'name': 'tom', 'age': 18, 'gender': 'male'}

对象的属性查找顺序

属性查找

  • 先从对象自己的名称空间找,没有则去类中找,如果类中也没有则报错
class BeijingStudent:    school = 'peking'    count = 0    aa = 10    def __init__(self, x, y, z):  # 会在调用类时自动触发        self.name = x        self.age = y        self.gender = z        BeijingStudent.count += 1        self.aa = 1    def choose_course(self):        print('is choosing course')
print(BeijingStudent.count)
0
stu1 = BeijingStudent('tom', 18, 'male')print(stu1.count)
1
stu2 = BeijingStudent('jerry', 19, 'male')print(stu2.count)
2
stu3 = BeijingStudent('shane', 25, 'male')print(stu3.count)
3
print(BeijingStudent.count)
3
  • 由于上述修改的是类属性,类属性的count已经被修改为3,所以其他实例的count都为3
print(stu1.count)print(stu2.count)print(stu3.count)
333
  • 由于aa是私有属性,因此stu们都会用私有的aa,不会用类的aa
print(stu1.__dict__)print(stu2.__dict__)print(stu3.__dict__)
{'name': 'tom', 'age': 18, 'gender': 'male', 'aa': 1}{'name': 'jerry', 'age': 19, 'gender': 'male', 'aa': 1}{'name': 'shane', 'age': 25, 'gender': 'male', 'aa': 1}

类与对象的绑定方法

类与对象的绑定方法

class BeijingStudent:    school = 'peking'    def __init__(self, name, age, gender):        self.name = name        self.age = age        self.gender = gender    def choose_course(self):        print(f'{self.name} is choosing course')    def func(self):        print('from func')
  • 类名称空间中定义的数据属性和函数属性都是共享给所有对象用的

  • 对象名称空间中定义的只有数据属性,而且是对象所独有的数据属性

类的绑定对象

stu1 = BeijingStudent('tom', 18, 'male')stu2 = BeijingStudent('jerry', 19, 'male')stu3 = BeijingStudent('shane', 25, 'male')print(stu1.name)print(stu1.school)
tompeking
  • 类中定义的函数是类的函数属性,类可以使用,但使用的就是一个普通的函数而已,意味着需要完全遵循函数的参数规则,该传几个值就传几个值。
print(BeijingStudent.choose_course)
try:    BeijingStudent.choose_course(123)except Exception as e:    print(e)
'int' object has no attribute 'name'

对象的绑定方法

  • 类中定义的函数是共享给所有对象的,对象也可以使用,而且是绑定给对象用的
  • 绑定的效果:绑定给谁,就应该由谁来调用,谁来调用就会将谁当作第一个参数自动传入
print(id(stu1.choose_course))print(id(stu2.choose_course))print(id(stu3.choose_course))print(id(BeijingStudent.choose_course))
2907183244104290718324410429071832441042907185353320
print(id(stu1.school))print(id(stu2.school))print(id(stu3.school))
290718531812829071853181282907185318128
print(id(stu1.name), id(stu2.name), id(stu3.name))
2907185317792 2907185319192 2907185317568
stu1.choose_course()stu2.choose_course()stu3.choose_course()
tom is choosing coursejerry is choosing courseshane is choosing course
  • 补充:类中定义的函数,类确实可以使用,但其实类定义的函数大多情况下都是绑定给对象用的,所以在类中定义的函数都应该自带一个参数self
stu1.func()
from func
BeijingStudent.func(1)
from func

类与数据类型

类与数据类型

  • Python3中统一了类与类型的概念,类就是类型
class Foo:    passobj = Foo()print(type(obj))
lis = [1, 2, 3]lis2 = [4, 5, 6]print(type(lis))
  • lis和lis2都是实例化的对象,因此lis使用append方法和lis2无关
lis.append(7)print(lis)
[1, 2, 3, 7]
print(lis2)
[4, 5, 6]

list.append()方法原理

class BeijingStudent:    school = 'peking'    def __init__(self, name, age, gender):        self.name = name        self.age = age        self.gender = gender    def choose_course(self, name):        print(f'{name} is choosing course')stu1 = BeijingStudent('tom', 18, 'male')
stu1.choose_course(1)  # BeijingStudent.choose_course(stu1,1)
1 is choosing course
BeijingStudent.choose_course(stu1, 1)
1 is choosing course
lis = [1, 2, 3]print(type(lis))
lis.append(4)print(lis)
[1, 2, 3, 4]
list.append(lis, 5)print(lis)
[1, 2, 3, 4, 5]

对象的高度整合

没有对象

  • 以连接数据库举例,如果没有面对对象的思想,我们只要想要使用一个方法,就必须得这样做
import pymysql  # 连接mysql的三方库,可以pip3 install pymysql安装def exc1(host, port, db, charset, sql):    conn = pymysql.connect(host, port, db, charset)    conn.execute(sql)    return xxxdef exc2(proc_name):    conn = pymysql.connect(host, port, db, charsett)    conn.call_proc(sql)    return xxxexc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t1')exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t2')exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t3')exc1('1.1.1.1', 3306, 'db1', 'utf-8', 'select * from t4')
  • 由于host、port、db、charset可能是固定不变的,sql一直在变化,因此我们通过上述的方法实现不同的sql语句,非常麻烦,因此我们可以改用默认形参
def exc1(sql, host='1.1.1.1', port=3306, db='db1', charset='utf-8'):    conn = pymysql.connect(host, port, db, charset)    conn.execute(sql)    return xxxexc1('select * from t1')exc1('select * from t2')exc1('select * from t3')exc1('select * from t4')
  • 虽然是用默认参数简化了操作,但是对于不同引用的对象,参数并不是一成不变的,或者我们需要对exc2方法进行修改,这是非常麻烦的,因此可以考虑使用面向对象

有对象

  • 有了面对对象之后,对于上述的例子,我们可以这样做
import pymysqlclass Foo:    def __init__(self, host, port, db, charset):        self.host = host        self.port = port        self.db = db        self.chartset = chartset    def exc1(self, sql):        conn = pymysql.connect(self.host, self.port, self.db, self.charset)        conn.execute(sql)        return xxx    def exc2(self, proc_name):        conn = pymysql.connect(self.host, self.port, self.db, self.charsett)        conn.call_proc(sql)        return xxxobj1 = Foo('1.1.1.1', 3306, 'db1', 'utf-8')obj1.exc1('select * from t1')obj1.exc1('select * from t2')obj1.exc1('select * from t3')obj1.exc1('select * from t4')obj2 = Foo('1.1.1.2', 3306, 'db1', 'utf-8')obj2.exc1('select * from t4')
  • 对于上述发生的现象,我们可以总结对象其实就是一个高度整合的产物,整合数据与专门操作该数据的方法(绑定方法)

转载于:https://www.cnblogs.com/WilliamKong94/p/11123172.html

你可能感兴趣的文章
原来今天是冬至
查看>>
又混了一天班
查看>>
九度oj 1006
查看>>
SQL Server 2008 允许远程链接 解决方法
查看>>
HDU6400-2018ACM暑假多校联合训练1004-Parentheses Matrix-构造
查看>>
最短路问题专题
查看>>
《Redis复制与可扩展集群搭建》看后感
查看>>
Jquery Mobile总结
查看>>
223. Rectangle Area
查看>>
spring boot + velocity中文乱码解决方式
查看>>
世锦赛7金MVP德雷塞尔真能接班菲鱼?同期成就不及1/5!
查看>>
读罢泪两行,人生成长必须面对的10个残酷事实
查看>>
ASP 32位程序运行与64位问题:ADODB.Connection 错误 '800a0ea9' 未指定提供程序,也没有指派的默认提供程序。...
查看>>
xcode-git笔记
查看>>
TCP和UDP的优缺点及区别
查看>>
MATLAB消除曲线毛刺Outlier Detection and Removal [hampel]
查看>>
JavaScript 正则表达式
查看>>
MySQL数据库安装和基本使用
查看>>
CSocket客户端(TCP)
查看>>
Unity Navigation自动寻路
查看>>