我们编程可分为两种编程思想:
面向过程:将程序进行流程化,即把程序的步骤整理清楚再一步步实现,但是拓展性差,程序的流程在写程序的时候已经决定好,后期更改程序会牵扯到有关联性的一些功能。
理解:面向过程关注的是解决问题需要哪些步骤
面向对象:将程序的变量以及功能整合到一起成为:对象
,程序的流程是在对象生成后决定的,后期拓展程序只需要更改对象(或实例化对象的类)即可
理解:面向对象关注的是解决问题需要哪些对象
但并不是说开发程序一定只用面向对象编程思想来进行开发,选取对我们更有优势的方式才是最好的!那么本篇就来介绍一下面向对象编程~
本篇主要介绍面向对象的基础内容
Python作为设计之初就是作为一种面向对象的编程语言。
什么是对象?目前可以理解为:有名称、属性、功能的集合体
其实在我们平常所使用python时就已经接触到对象
拿定义一个变量来举例:所列出的方法是x这个字符所具备的吗?
并不是,我们可以看成:x = int(10) 这样更利于理解,因为我们输入10,Python会检测到我们输入的内容进而帮我们转换为对应的数据类型。可以理解成:10是由int产生的,之后我们将10赋给一个变量,这个变量此时就可以称之为:对象
那么我们来说一下如何产生对象。
上序所说的int就是一个类名,Python中对象是由调用类而实例化出的
类的定义:由class关键字产生
class 类名:
<statement...>
那么我们获取对象则是调用定义的类名
class Person: # 类名的定义推荐采用驼峰体:即单词的首字母大写
age = 10 # 类的属性
def f(self):
print('Hello class')
p = Person() # 那么我们通过调用Person这个类,实例化出一个名为:p的对象
print(p.age) # 访问这个类的属性
p.f() # 访问这个类的方法
我们会注意到:在类里面def创建函数时,会自动产生一个self的参数。这个待往下了解会提到,暂时不用在意
在定义类后,会产生一个名称空间,我们可以通过类名.__dict__
来进行查看
print(Person.__dict__)
{
'__module__': '__main__', 'age': 10, 'f': <function Person.f at 0x7fc95eb9edc0>, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}
# 可以看到一堆这样字典内容,__开头的我们不需要关注,这里看到age它是我们定义的一个类属性
对象也具备__dict__
可以查看其名称空间
p = Person()
print(p.__dict__)
{
}
我们可以看到p
这个对象,名称空间内并无任何内容,仔细观察上面调用时可以发现,我们调用的是类的属性,并不是自己的,这就涉及到一个查找属性的优先级:
对象查找属性:优先查找自身是否具备这个属性,如果不具备则到对应的类中去查找,再未找到则报错,我们目前了解到这里即可,后续会涉及到继承查找
接着来把上序类里面方法有个一个参数名为self
因为类里面的属性以及函数都是提供给对象使用的,而如果类本身来调用它就与普通函数无异了,该传递几个参数就传递几个。所以我们着重解释self
的作用
拿例子比喻:
class Person:
age = 10
def f(self):
print('Hello class')
p = Person()
p.f() # 访问这个类的方法
它的作用就是,我们这个p对象
在调用类时,就会将类里面的f方法
绑定给p对象
,在调用这个f方法
时,会自动将与之绑定的对象传递进去,当然参数也可以不是self,但是在Python中约定通常使用self字符
作为参数
self(自己):这里也可以理解为,调用这个方法的对象
类里面的方法是共享给所有对象的,谁来调用它,它就与之进行绑定,我们在这个方法里面就可以获取绑定对象的属性
class Person:
age = 10
def f(self):
print('Hello class')
p1 = Person()
p2 = Person()
print(Person.f)
print(p1.f)
print(p2.f)
执行结果
<function Person.f at 0x7f8059a9edc0>
<bound method Person.f of <__main__.Person object at 0x7f8059a6dfd0>>
<bound method Person.f of <__main__.Person object at 0x7f8059a6de80>>
# 可以看到,通过类调用里面的函数它就只是普通函数
# 我们通过对象调用它就成了方法,虽说方法只有一个,但是每次传递进去的对象都是不同的
# 所以产生的效果也不同,self准确来说就是接收传递进来的对象
给对象添加一些属性,而不是去类里面拿,访问这个对象自身就能拿到值
# 和上序一样的内容,我们做点手脚!
class Person:
age = 10
def f(self):
print('Hello class')
p = Person()
p.age = 1
print(p.age)
# 此时我们打印出来的内容就是这个p对象本身的age属性值,而不是去类里面查找属性
>>> 1
就是说,当我们对象自身拥有这个属性时,就不会跑到类里面去找!
再来绕一下,看看是否了解:根据下列代码说出打印内容
p1 = Person()
p1.age += 1
p2 = Person()
print(p1.age)
print(p2.age)
p1.age的执行为:先在p1这个对象里面查找,发现没有,再去类里面查找,找到内容以后+1后,将age这个属性赋给p1这个对象。p1具备了age这个属性,值为:11。
而p2.age没有在自身这个对象找到,则去类里面找到,打印出来
在调用类的过程中将我们需要的属性就给定义好,实例化对象后,直接调用这个属性即可。
类里面具备一个__init__
方法,注意:是init ,因为类里面同样有一个极其相似的方法,就是int,不一样的方法,实现的效果不同,切记!
定义方法:
class Person:
def __init__(self):
给对象初始化的属性
使用方式:在__init__
里面接收我们在调用类时传递进来的参数再赋给对象
class Person:
def __init__(self,name,age): # 在调用类时,自动触发这个方法的运行
self.name = name
self.age = age
p = Person('jack',18)
print(p.name)
print(p.age)
执行效果:可以看到p对象已经拥有自己的属性
jack
18
经过了解绑定方法以后,我们可以知道,上序self
可以代表p对象,而self.name = name
则是给p对象添加一个name属性
而属性值则是我们调用类时传递进去的。
在类里面调用方法需要携带self
class Person:
def f1(self):
print('f1')
def f2(self):
self.f1()
print('f2')
p = Person()
p.f2()
执行结果
'f1'
'f2'
这是我们可以再来看平常所定义的列表
l = [1,2,3,4,5] # 平常都是这样定义的,那么我们可以这样
# l = list([1,2,3,4,5]) 其实就是经过了list这个类而产生的,只不过我们平时不会这样写,因为Python会帮我们转换
# 那么这个l就属于一个对象了,因为它是经历过调用类而实例化出的,所以它也有一些方法
l对象
的方法都是由list这个类提供的,因为它本身就是由list类
产生的
那么再来与我们上序讲到的对象绑定方法
结合就能理解,定义两个列表(对象)
l1 = [1,2,3,4,5]
l2 = [5,4,3,2,1]
l1.append(6)
l2.append(0)
那我们调l1对象
里面的方法与l2对象
无关吧?因为它们都是实例化出的对象,每一个都是独立的,哪个对象调用append()
这个方法也只是将这个对象传递进去,第二步再将我们需要给这个对象属性增加的值传递进去。
可以看到,也是由self
参数接收了我们调用这个方法的对象,再是跟传递进来内容,只是由于这是个内置类(或C语言写的进行过编译)方法,所以看不到源码,也不用在意
原理就是
l = [1,2,3,4,5]
l.append(6) # 等同于 list.append(l,6) 第一个是对象,第二个是值
# 可以明白,第一个是传入的对象,第二个才是传入的值,那么我们就可以调用list这个类给l对象追加值
list.append(l,7)
print(l)
打印结果
[1, 2, 3, 4, 5, 6, 7]
重点:
在前面我们经常使用type()
来查看我们变量值的属性,其实在学习面向对象以后可以得知,它反馈的只是我们这个变量值是由哪个类而产生的
l = [1,2,3,4,5]
print(type(l))
打印结果
<class 'list'>
Python统一了类与类型的概念:类就是类型
面向对象并不会使代码有所减少,但是更利于调用与拓展,我们可以通过几个练习来观察面向过程与面向对象之间的区别。
链接中存在3个源码文件:
有两个爬取梨视频网页的源码,实现效果一直,但所写方法不同。
有一个使用面向对象来模拟王者荣耀英雄对战的源码文件。
百度网盘:https://pan.baidu.com/s/13jM3eNwhASAB20wONuKCVg?errmsg=Auth+Login+Sucess&errno=0&ssnerror=0list/path=%2F&parentPath=%2F
提取码:mwql
有兴趣可以尝试写一下!!有助于巩固面向对象
的基础内容
下一章 进阶篇:https://blog.csdn.net/m0_46958731/article/details/111603575
技术小白记录学习过程,有错误或不解的地方请指出,如果这篇文章对你有所帮助请
点赞 收藏+关注
子夜欢迎您的关注,谢谢支持!