面向过程编程:
- 核心是"过程"二字,过程指的是做事情的步骤,即先做什么再做什么
- 基于该编程思想编写程序,就好比一条工厂流水线,一种机械式的思维方式
优点:
- 逻辑清晰,复杂的问题流程化,进而简单化
缺点
- 可扩展性差
面向对象编程
- 核心是"对象"二字,对象指的是特征与技能的结合体
- 基于该编程思想编写程序,就好比在创造世界,一种上帝式的开发方式
优点:
- 可扩展性高
缺点
- 编写程序的复杂程度远高于面向过程编程思想
优先使用面向过程还是面向对象?
- 面向过程结合面向对象对象一起使用
类与对象
- 在现实社会中:
- 对象是一个个具体存在的事物,类是由人类文明的发展抽象总结出来的
- 在程序中:
- 必须遵循,先有类,再有对像
对象是特征与技能的结合体,类是一系列具有相同特征与技能的对象的结合体
如何定义类
-
定义类的语法
''' class 类名: 对象相同的特征 对象相同的技能 '''
- 类名用来调用创造对象
- 类名必须用循驼峰体式,变量名与函数名使用下划线式
- 相同特征:类内部的变量
- 相同技能:类内部的函数
-
定义类时发生的事情
- 类在定义时会产生一个空的名称空间.
- 执行类体代码
- 把执行类体代码产生的所有的名字,扔进类的名称空间中
补充
'''
1. __module__ 与__name__ 都是存储当前文件状态(执行文件还是模块文件)的变量,如果为执行文件他们的值都为 "__main__"
2. __doc__ 表示是存储解释型文档内容的变量
3. __weakref__ 表示弱引用
4. 函数定义阶段函数名存放在全局名称空间中,调用阶段会新开辟局部名称空间存放函数体代码执行产生的名字
'''
类和对象详解
#__dict__获取的类名称空间数据只支持查,不支持改/增/删
'''
查看类名称空间中所有名字
print(OldboyStudent.__dict__)
查
print(OldboyStudent.__dict__['school'])
改
OldboyStudent.__dict__['school'] = 'oldgirl' #报错
增
OldboyStudent.__dict__['name'] = 'oldgirl' #报错
删
del OldboyStudent.__dict__['school'] #报错
'''
**类.特征或技能 **的方式可以对内部名字进行修改
"." 会指向类内部的名称空间从而获取属性
如何产生对象
- 语法:
- 类名 + () 调用类产生对象
名称空间的产生
- 类的名称空间在类定义阶段就已经产生
- 对象的名称空间,在调用类时产生
定制对象独有特征
#通过 __init__ 内置函数实现,调用类会自动调用该函数,为对象初始化某些属性,而不仅仅只是定义该函数
调用类发生的事情
'''
#1.首先会产生一个空的对象,就是产生"对象的名称空间"
#2.会自动调用 __init__ 函数
#3.会将对象本身以及类括号内的参数一并传给 __init__ 函数
'''
对象与类的查找顺序
- 对象.属性 ,优先查找对象自己的
- 若对象本身没有,则去类里面找
- 若类里面也没有,则报错
class OldboyStudent:
SCHOOL = 'oldboy'
NAME = 'DDDDDDDD'
def __init__(self, name, age, sex, school):
self.name = name
self.age = age
self.sex = sex
self.SCHOOL = school
print(OldboyStudent.__dict__)
stu1 = OldboyStudent('小正正', 17, 'male', 'oldgirl')
print(stu1.__dict__)
print(stu1.SCHOOL)
对象的绑定方法
类内部的函数主要是给对象用的
- 由类来调用类内部的函数,该函数只是一个普通函数,普通参数需要接收几个参数就得传入几个参数
- 由对象来调用类中定义的函数称之为对象的绑定方法,该函数会绑定给对象使用,并且会将对象当做该绑定方法的第一个参数自动传入
stu = OldboyStudent('高凤凤1', 73, 'female')
print(stu.learn)
# <bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x000002AE13721A90>>
对象的绑定方法与类中对应的方法功能是一样的但是内存地址不一样
python中一切皆对象
def learn(course,self):
print(f'{self.name}learn python...') #类中的函数
stu1 = OldboyStudent('高凤凤1', 73, 'female')
stu1.learn('python') #对象默认当做第一个参数传入
#AttributeError: 'str' object has no attribute 'name'
def learn(course,self):
print(f'{course.name}learn python...')
stu1 = OldboyStudent('高凤凤2', 84, 'male')
stu1.learn('python')
#高凤凤2learn python...
def __init__(self, seq=()): # known special case of list.__init__
"""
list() -> new empty list
list(iterable) -> new list initialized from iterable's items
# (copied from class doc)
"""
pass
lt = [1,2,3] #lt = list([1,2,3])
#源码
def __init__(self, seq=()): # known special case of list.__init__
"""
list() -> new empty list
list(iterable) -> new list initialized from iterable's items
# (copied from class doc)
"""
pass
class Foo:
pass
print(Foo) #获取类变量名值---类对象(及类对象地址,该地址固定)
print(id(Foo)) #获取存储类对象的地址,该地址不固定
def f():
pass
print(f) #获取函数变量名的值---函数对象及其地址,该地址固定.
print(id(f)) #获取存储函数对象及其地址的地址,该地址不固定
'''
<class __main__.Foo at 0x00E2B030>
2196271763032
<function f at 0x000001FF55291F28>
2196157046568
'''
人狗大作战
#人狗大作战
class Dog: #定义狗类
#狗名/狗的生命值/狗的攻击力
def __init__(self,name,life,aggr):
self.name = name
self.life = life
self.aggr = aggr
#狗咬的技能
def bite(self,object):
if self.life <= 0:
print(f'{self.name}死的时候生命值为{self.life}')
return True
if object.life <= 0:
print(f'{object.name}死的时候生命值为{object.life}')
return True
object.life -= self.aggr
print(f'{self.name}咬{object.name},{object.name}生命值还剩{object.life}')
class People: # 定义人类
# 人名/人的生命值/人的攻击力
def __init__(self, name,life,aggr):
self.name = name
self.life = life
self.aggr = aggr
# 人咬的技能
def bite(self, object):
if self.life <= 0:
print(f'{self.name}死的时候生命值为{self.life}')
return True
if object.life <= 0:
print(f'{object.name}死的时候生命值为{object.life}')
return True
object.life -= self.aggr
print(f'{self.name}咬{object.name},{object.name}生命值还剩{object.life}')
egon = People('egon', 1000, 200)
d = Dog('哈士奇',400, 500)
while True:
res1 = egon.bite(d)
if res1:
break
res2 = d.bite(egon)
if res1:
break
'''
egon咬哈士奇,哈士奇生命值还剩200
哈士奇咬egon,egon生命值还剩500
egon咬哈士奇,哈士奇生命值还剩0
哈士奇死的时候生命值为0
哈士奇死的时候生命值为0
'''