python知识体系第七节——面向对象初步

1 面向过程编程与面向对象编程的区别

面向过程思维强调的是通过一定的步骤取解决某个具体复杂度较低的问题,将某个具体问题的解决办法分解为step1,step2,…stepn。例如炒菜即可通过将问题分解为一个个小的步骤去完成,但如果像满汉全席这样的菜,涉及的菜品很多,其中的方法步骤就更多了,显然仅仅使用面向过程的思维一步步的解决并不适用,这时面向对象的思维就发挥出其优势了。比如满汉全席有108道菜,那么每一道菜就是一个对象,每道菜又包含了所需的材料,又包含了各个对象。其实面向对象就是系统化思维,而面向过程就是流程化思维,两种思维各有适用的情况。而python使用的是面向对象的编程思维,这使得python对于处理复杂问题效率极高。

2 类(class)

类的概念:python中的数据类型包含字符串(str)、整数(int)、浮点数(float)、列表(list)、集合(set)、字典(map)、元组(tuple)、函数(function),python是面向对象的编程模式,这些数据类型都是包含关系,比如首先是简单的字符串、整数等数据类型,接着是列表将这些数据类型包含起来,再接着是由函数将列表、集合等包含起来,这些都是由于问题越来越复杂,对象越来越多,那j么函数由什么包含呢,这时就出现了类(class)的概念,我们知道,函数的定义方式为 def f(x1,x2,…xn):<函数体>,函数是什么,函数就是使一组参数去执行某一个特定的功能,那么为了使函数去执行多个功能便出现了类的概念,类(class)是指给某一组参数去执行类所定义的所有功能,类的一般形式如下:

class <类名称(一般首字母大写)>def __init__(self,参数1,参数2,...,参数n):
		self.参数1=参数1
		self.参数2=参数2
		......
		self.参数n=参数n
	def f1(self):
		<函数体>
	def f2(self):
		<函数体>
	def f3(self):
		<函数体>
	...........
	def fn(self):
		<函数体>
	#__init__()函数一般为构造函数,其中系统会默认第一个参数为self,构造函数的意义在于初始化对象,比如一个类有100个功能函数,显然给每一个函数都输入一遍参数是十分麻烦的,并且调用的时候也非常麻烦,定义了构造函数以后,后面的功能函数都无需再输入参数,因为在构造函数里面已经经过定义,所有的参数直接使用self即可指代,相当于self囊括了所有的参数。
调用class类:
1.给类赋值,这就时类的作用所在,类可以赋予参数一系列的功能,这是函数办不到的,比如一个学生是一个类,会有一系类特征比如年龄、身高、体重、考试分数、专业,那么如果想对这些参数进行一系列不同的处理显然如果每次都去调用函数然后去输入参数会比较麻烦,那么就把这一类函数归纳起来,叫做类(class)。
<类名称>	(参数1,2..,n)	
2. 调用类函数形式:
<类名称>.fn()
就像引用库一样。
class Student:
    def __init__(self,name,score):
        self.name=name
        self.score=score

    def chaxunfenshu(self):
        print('{}的分数是{}'.format(self.name,self.score))

    def buzhizuoye(self):
        print('{}的家庭作业是抄一首古诗'.format(self.name))

student1=Student('张三',100)
student1.chaxunfenshu()
student2=Student('李四',100)
student2.buzhizuoye()

3 类对象、类变量、类方法、静态方法

类变量、实例变量

类对象:类也是对象,当创建了类以后,也会生成对象。

class Student:
    pass
print(type(Student))
print(id(Student))
print(Student)

类变量:类中不仅可以有函数,也可以定义变量,定义变量可以供后面所定义的函数使用。
类属性的定义方式:
class 类名:
类变量名= 初始值

class Student:
    company = "***" #类属性
    count = 0 #类属性
    def __init__(self,name,score):
        self.name = name #实例属性
        self.score = score
        Student.count = Student.count+1
    def say_score(self): #实例方法
        print("我的公司是:",Student.company)
        print(self.name,'的分数是:',self.score)
s1 = Student('张三',80) #s1 是实例对象,自动调用__init__()方法
s1.say_score()
s2=Student('李四',90)
s2.say_score()
print('一共创建{0}个 Student 对象'.format(Student.count))

类方法与静态方法:类中有通过构造函数、实例函数搭建的实例方法,def init(self,x1,x2…),def f(self),python中还有类方法及静态方法,这些方法不能调用self中包含的实例变量(x1,x2,…)(注意实例方法可以调用类变量),可以重新定义形参及调用类变量,类方法的定义形式为:
@classmethod
def 类方法名(cls,[形参列表]):
函数体
其中@classmethod是装饰器,规则要点如下:
1. @classmethod必须位于方法上面一行
2. cls必须有,cls指的是类对象本身
3. 调用的类方法的形式为 类名.类方法名(参数列表)
4. 类方法中调用的参数不能是实例属性与方法,否则会报错
5. 子类继承父类方法时,传入 cls 是子类对象,而非父类对象
静态方法: 类中也可以有不需要指代变量self,cls的函数,静态方法
静态方法的一般形式为:
@staticmethod
def 静态方法名([形参列表]):
函数体
同样,静态方法也有以下几种要点需要注意:
1. @staticmethod必须位于函数上面一行
2. 不能调用实例参数
3. 调用方法为“类名.静态方法名(参数列表)”

class Student():
    a='王麻子'
    count=0
    time='21:00'
    homeworks='背诵唐诗三百首第一首'
    def __init__(self,name,score):
        self.name=name
        self.age=score
        Student.count = Student.count + 1

    def printage(self):
        print('{}的分数是{}'.format(self.name,self.age))

    @classmethod
    def homework(cls):
        print('{}的作业是{}'.format(Student.a,Student.homeworks))
    @staticmethod
    def sleeptime(b):
        print('{}的睡觉时间为{}'.format(b,Student.time))
Student1=Student('张三',98)
Student2=Student('李四',100)
Student1.printage()
Student2.printage()
print(Student.count)
Student1.homework()
Student1.sleeptime('李二狗')

输出结果:
张三的分数是98
李四的分数是100
2
王麻子的作业是背诵唐诗三百首第一首
李二狗的睡觉时间为21:00

4 _del_方法(析构函数)和垃圾回收机制

基本上所有支持OOP设计的语言都支持析构方法(也称析构函数),析构方法都是在对象生命周期结束时调用,一般用来实施实例相关生命周期内访问数据的扫尾工作,包括关闭文件、释放内存、输出日志、清理数据等。Python 实现自动的垃圾回收,当对象没有被引用时(引用计数为 0),由垃圾回收器 调用__del__方法。 我们也可以通过 del 语句删除对象,从而保证调用__del__方法。 系统会自动提供__del__方法,一般不需要自定义析构方法。

class Foo:

    def __del__(self):
        print('执行我啦')

f1=Foo()

print('------->')

输出结果:
------->
执行我啦

5 _call_函数

在类中定义call函数可以实现变量像函数一样直接调用,实际上函数的本质也是call函数。通过下面的例子可以看出,__call__函数相当于另变量也拥有了函数的功能。这时变量A成为了可调用的对象,一般称为可调用对象,实际上函数就是可调用对象。

class A:
    def __init__(self,a,b):
        self.a=a
        self.b=b

    def __call__(self):
        print('{}+{}={}'.format(self.a,self.b,self.a+self.b))
A1=A(1,1)
A1()
输出结果:
1+1=2

或者下面的代码

class A:
    def __call__(self,a,b):
        print('{}+{}={}'.format(a,b,a+b))
A1=A()
A1(1,1)
输出结果:
1+1=2

6 方法的动态性

方法的动态性意思是当类创建好以后,可以为类添加函数或更改类中的函数,示例代码如下:
需要注意的是,新增或者替换的函数都需要对形参重新赋值,即原来赋予self的实例参数都不再有效。

class Car:
    def __init__(self,price):
        self.price=price


    def carprice(self):
        print('这辆车的价格是:{}'.format(self.price))

def carbrand_(self,brand):
    print('这辆车的品牌是{}'.format(brand))
def carprice1(self,price):
    print('这辆车的价格是:{}元'.format(price))

Car.carbrand=carbrand_
Car1=Car(100000)
Car1.carprice()
Car1.carbrand('大众')
Car.carprice=carprice1
Car1.carprice(50000)

输出结果:
这辆车的价格是:100000
这辆车的品牌是大众
这辆车的价格是:50000

7 私有属性与方法

封装在类里面的实例属性,如果不想被其他人访问,可以将该方法设置成为私有属性或者私有方法。

当私有属性没有隐藏的时候,学生的属性是可以调用的,代码如下:

class Student():
    def __init__(self,name,age,score):
        self.name=name
        self.age=age
        self.score=score
Student1=Student('张三',18,100)
print(Student1.name,Student1.age,Student1.score)
输出结果:
张三 18 100

当私有属性被隐藏age被隐藏时,显示错误代码为’Student’ object has no attribute ‘age’,说明年龄这一属性已经被私有化了,无法被查询,如果想要访问,在类名前面加下划线,在属性名前面加双下划线,代码如下:

class Student():
    def __init__(self,name,age,score):
        self.name=name
        self.__age=age
        self.score=score
Student1=Student('张三',18,100)
print(Student1.name,Student1.age,Student1.score)
输出结果:
Traceback (most recent call last):
  File "C:/Users/Administrator/Desktop/练习代码/测试代码05.py", line 98, in <module>
    print(Student1.name,Student1.age,Student1.score)
AttributeError: 'Student' object has no attribute 'age'
-------------------------------------------------------------------------------
class Student():
    def __init__(self,name,age,score):
        self.name=name
        self.__age=age
        self.score=score
Student1=Student('张三',18,100)
print(Student1.name,Student1._Student__age,Student1.score)

输出结果:
张三 18 100

8 @property装饰器

装饰器的作用在于能够将类中的实例方法像实例属性一样进行调用,如下代码所示,当未使用装饰器的时候,当使用方法Car1.printbrand进行调用的时候,输出了Car.brand的地址,并未调用该实例方法:

class Car():
    def __init__(self,price,brand):
        self.price=price
        self.brand=brand

    def printprice(self):
        print('该汽车的价格为 :{}'.format(self.price))

    def printbrand(self):
        print('该汽车的品牌为:{}'.format(self.brand))

Car1=Car(100000,'大众')
print(Car1.price)
print(Car1.brand)
Car1.printprice()
Car1.printbrand()
print(Car1.printbrand)
print(Car1.printprice)

输出结果:
100000
大众
该汽车的价格为 :100000
该汽车的品牌为:大众
<bound method Car.printbrand of <__main__.Car object at 0x000001EE390DB608>>
<bound method Car.printprice of <__main__.Car object at 0x000001EE390DB608>>

下面的3段代码
第一段为使用装饰器的代码,除了在两个函数前加入装饰器以外,其他语句均不变,输出结果显示TypeError: ‘NoneType’ object is not callable,说明此时Car1.printprice()的调用方式是错误的。
第二段使用@property装饰器装饰<def printprice(self):>, 函数当删除Car1.printprice()/Car1.printbrand()这两句语句以后,再来看结果,结果说明可以直接调用,但此时Car1.printprice是没有办法进行直接修改的,需要使用setter对函数进行设置,这样就可以进行修改与定义了。
第三段代码则使用@printprice.setter对printprice函数进行设置,这样则可以对Car1.printprice进行重新定义。

class Car():
    def __init__(self,price,brand):
        self.price=price
        self.brand=brand
    @property
    def printprice(self):
        print('该汽车的价格为 :{}'.format(self.price))
    @property
    def printbrand(self):
        print('该汽车的品牌为:{}'.format(self.brand))

Car1=Car(100000,'大众')
print(Car1.price)
print(Car1.brand)
Car1.printprice()
Car1.printbrand()
print(Car1.printbrand)
print(Car1.printprice)

输出结果:
Traceback (most recent call last):
100000
  File "C:/Users/Administrator/Desktop/练习代码/测试代码05.py", line 114, in <module>
    Car1.printprice()
大众
TypeError: 'NoneType' object is not callable
该汽车的价格为 :100000
-------------------------------------------------------------------
class Car():
    def __init__(self,price,brand):
        self.price=price
        self.brand=brand
    @property
    def printprice(self):
        print('该汽车的价格为 :{}'.format(self.price))
    @property
    def printbrand(self):
        print('该汽车的品牌为:{}'.format(self.brand))

Car1=Car(100000,'大众')
print(Car1.price)
print(Car1.brand)

print(Car1.printbrand)
print(Car1.printprice)

输出结果:
大众
该汽车的品牌为:大众
None
该汽车的价格为 :100000
None
------------------------------------------------------------------------------
class Car():
    def __init__(self,price,brand):
        self.price=price
        self.brand=brand
    @property
    def printprice(self):
        print('该汽车的价格为 :{}'.format(self.price))
    
    @printprice.setter
    def printprice(self,price):
        if 100000<price<500000:
            self.price = price
        else:
            print('汽车价格不在可允许的范围内,请重新输入!')
    @property
    def printbrand(self):
        print('该汽车的品牌为:{}'.format(self.brand))

Car1=Car(100000,'大众')
print(Car1.price)
print(Car1.brand)
Car1.printprice=5000
print(Car1.printbrand)
print(Car1.printprice)

输出结果:
100000
大众
汽车价格不在可允许的范围内,请重新输入!
该汽车的品牌为:大众
None
该汽车的价格为 :100000
None
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值