【Python基础知识-pycharm版】面向对象初步

面向对象初步

面向对象(Object oriented Programming,OOP)编程的思想主要是针对大型 软件设计而来的。面向对象编程使程序的扩展性更强、可读性更好,使的编程可以像搭 积木一样简单。
面向对象编程将数据和操作数据相关的方法封装到对象中,组织代码和数据的方式 更加接近人的思维,从而大大提高了编程的效率。
Python完全采用了面向对象的思想,是真正面向对象的编程语言,完全支持面向 对象的基本功能,例如:继承、多态、封装等。
Python中,一切皆对象。数据类型、函数等,都是对象。
注:Python支持面向过程、面向对象、函数式编程等多种编程范式。

面向对象和面向过程区别

面向过程(Procedure Oriented)思维

面向过程编程更加关注的是“程序的逻辑流程”,是一种“执行者”思维,适合编写小 规模的程序。
面向过程思想思考问题时,首先思考“怎么按步骤实现?”并将步骤对应成方法, 一步一步,最终完成。 这个适合简单任务,不需要过多协作的情况下。

面向对象(Object Oriented)思维

面向对象更加关注的是“软件中对象之间的关系”,是一种“设计者”思维,适合编写 大规模的程序。
面向对象(Object)思想更契合人的思维模式。首先思考的是“怎么设计这个事物?”
面向对象可以帮助我们从宏观上把握、从整体上分析整个系统。 但是,具体到 实现部分的微观操作(就是一个个方法),仍然需要面向过程的思路去处理。
面向对象离不开面 向过程!
面向对象思考方式
遇到复杂问题,先从问题中找名词(面向过程更多的是找动词),然后确立这些名词哪些可以作为类,再根据问题需求确定的类的属性和方法确定类之间的关系

面向对象和面向过程的总结

都是解决问题的思维方式,都是代码组织的方式。
解决简单问题可以使用面向过程
解决复杂问题:宏观上使用面向对象把握,微观处理上仍然是面向过程。

对象的进化

随着编程面临的问题越来越复杂,编程语言本身也在进化,从主要处理简单数据开始, 随着数据变多进化“数组”; 数据类型变复杂,进化出了“结构体”; 处理数据的方式和逻辑变复杂,进化出了“对象”。

  1. 简单数据
    像 30,40,50.4 等这些数字,可以看做是简单数据。最初的计算机编程,都是像这样 的数字。
  2. 数组
    将同类型的数据放到一起。比如:整数数组[20,30,40],浮点数数组[10.2,11.3, 12.4], 字符串数组:[“aa”,”bb”,”cc”]
  3. 结构体
    将不同类型的数据放到一起,是 C语言中的数据结构。比如: struct resume{ int age; char name[10]; double salary; };
  4. 对象
    将不同类型的数据、方法(即函数)放到一起,就是对象。
class Student:
company = "wps" #类属性 
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)

数字也是对象。比如:整数9,就是一个包含了加法、乘法等方法的对象。

类的定义

通过类定义数据类型的属性(数据)和方法(行为),也就是说,“类将行为和状态打 包在一起”。
在这里插入图片描述
对象是类的具体实体,一般称为“类的实例”。
从一个类创建对象时,每个对象会共享这个类的行为(类中定义的方法),但会有自己的属 性值(不共享状态)。更具体一点:“方法代码是共享的,属性数据不共享”。
在这里插入图片描述
Python中,“一切皆对象”。类也称为“类对象”,类的实例也称为“实例对象”。
定义类的语法格式如下: class 类名: 类体
要点如下:

  1. 类名必须符合“标识符”的规则;一般规定,首字母大写,多个单词使用“驼峰原则”。
  2. 类体中我们可以定义属性和方法。
  3. 属性用来描述数据,方法(即函数)用来描述这些数据相关的操作。
class Student: 
	def __init__(self,name,score): #构造方法第一个参数必须为 self
		self.name = name #实例属性 
		self.score = score

	def say_score(self): #实例方法 
		print(self.name,'的分数是:',self.score)

s1 = Student('张三',80) #s1 是实例对象,自动调用__init__()方法 s1.say_score()

__init__构造方法和__new__方法

类是抽象的,也称之为“对象的模板”。通过类这个模板,创建类的实例对象,然 后才能使用类定义的功能。
之前一个 Python 对象包含三个部分:id(identity 识别码)、type(对象类型)、 value(对象的值)。
更进一步的说,一个 Python 对象包含如下部分:

  1. id(identity 识别码)
  2. type(对象类型)
  3. value(对象的值)
    (1) 属性(attribute)
    (2) 方法(method)

创建对象,需要定义构造函数__init__()方法。构造方法用于执行“实例对象的初始化工作”,即对象创建后,初始化当前对象的相关属性,无返回值。
init()的要点如下:

  1. 名称固定,必须为:init()
  2. 第一个参数固定,必须为:self。 self指的就是刚刚创建好的实例对象。
  3. 构造函数通常用来初始化实例对象的实例属性,
  4. 通过“类名(参数列表)”来调用构造函数。调用后,将创建好的对象返回给相应的变量。
  5. init()方法:初始化创建好的对象,初始化指的是:“给实例属性赋值”
  6. new()方法: 用于创建对象,但我们一般无需重定义该方法。
  7. 如果我们不定义__init__方法,系统会提供一个默认的__init__方法。如果我们定义了带参 的__init__方法,系统不创建默认的__init__方法。

  1. Python中的self 相当于C++中的 self 指针, JAVA和C#中的this 关键字。Python 中, self必须为构造函数的第一个参数,名字可以任意修改。但一般遵守惯例,都叫做 self。

实例属性和实例方法

实例属性

实例属性是从属于实例对象的属性,也称为“实例变量”。他的使用有如下几个要点:

  1. 实例属性一般在__init__()方法中通过如下代码定义:
    self.实例属性名 = 初始值
  2. 在本类的其他实例方法中,也是通过self 进行访问:
    self.实例属性名
  3. 创建实例对象后,通过实例对象访问:
    obj01 = 类名() #创建对象,调用__init__()初始化属性
    obj01.实例属性名 = 值 #可以给已有属性赋值,也可以新加属性

实例方法

实例方法是从属于实例对象的方法。实例方法的定义格式如下:
def 方法名(self [, 形参列表]): 函数体
方法的调用格式如下: 对象.方法名([实参列表])
要点:

  1. 定义实例方法时,第一个参数必须为self。和前面一样,self 指当前的实例对象。
  2. 调用实例方法时,不需要也不能给self 传参。self 由解释器自动传参。

函数和方法的区别

  1. 都是用来完成一个功能的语句块,本质一样。
  2. 方法调用时,通过对象来调用。方法从属于特定实例对象,普通函数没有这个特点。
  3. 直观上看,方法定义时需要传递self,函数不需要。

实例对象的方法调用本质
在这里插入图片描述
其他操作

  1. dir(obj)可以获得对象的所有属性、方法
  2. obj.dict 对象的属性字典
  3. pass 空语句
  4. isinstance(对象,类型) 判断“对象”是不是“指定类型”

类对象、类属性、类方法、静态方法

类对象

类定义格式中,“class 类名:”实际上,当解释器执行class 语句时, 就会创建一个类对象。
【注】pass 为空语句。就是表示什么都不做,只是作为一个占位符存在。当你写代码时, 遇到暂时不知道往方法或者类中加入什么时,可以先用 pass占位,后期再补上。

类属性

类属性是从属于“类对象”的属性,也称为“类变量”。由于,类属性从属于类对象,可以 被所有实例对象共享。
类属性的定义方式: class 类名: 类变量名= 初始值
在类中或者类的外面,可以通过:“类名.类变量名”来读写。

类方法

类方法是从属于“类对象”的方法。类方法通过装饰器@classmethod来定义,格式如下:
@classmethod
def 类方法名(cls [,形参列表]) : 函数体
要点如下:

  1. @classmethod必须位于方法上面一行
  2. 第一个cls 必须有;cls指的就是“类对象”本身;
  3. 调用类方法格式:“类名.类方法名(参数列表)”。 参数列表中,不需要也不能给 cls 传 值。
  4. 类方法中访问实例属性和实例方法会导致错误
  5. 子类继承父类方法时,传入cls 是子类对象,而非父类对象

静态方法

Python中允许定义与“类对象”无关的方法,称为“静态方法”。
“静态方法”和在模块中定义普通函数没有区别,只不过“静态方法”放到了“类的名字空 间里面”,需要通过“类调用”。
静态方法通过装饰器@staticmethod来定义,格式如下:
@staticmethod
def 静态方法名([形参列表]) : 函数体
要点如下:

  1. @staticmethod必须位于方法上面一行
  2. 调用静态方法格式:“类名.静态方法名(参数列表)”。
  3. 静态方法中访问实例属性和实例方法会导致错误

内存分析实例对象和类对象创建过程(重要)

class Student: 
	company = "wps" #类属性 
	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() 
print('一共创建{0}个 Student 对象'.format(Student.count))

在这里插入图片描述

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

__del__方法称为“析构方法”,用于实现对象被销毁时所需的操作。比如:释放对象 占用的资源,例如:打开的文件资源、网络连接等。
Python实现自动的垃圾回收,当对象没有被引用时(引用计数为 0),由垃圾回收器 调用__del__方法。
通过del 语句删除对象,从而保证调用__del__方法。
系统会自动提供__del__方法,一般不需要自定义析构方法。

# 析 构 函 数 
class Person:
def __del__(self): 
	print("销毁对象:{0}".format(self))

p1 = Person() 
p2 = Person() 
del p2 
print("程序结束")

#运算结果: 
销毁对象:<__main__.Person object at 0x02175610> 
程序结束 
销毁对象:<__main__.Person object at 0x021755D0>

__call__方法和可调用对象

定义了__call__方法的对象,称为“可调用对象”,即该对象可以像函数一样被调用。
class SalaryAccount: 
	'''工 资 计 算 类'''
	def __call__(self, salary): 
		yearSalary = salary*12 
		daySalary = salary//30 
		hourSalary = daySalary//8
		return dict(monthSalary=salary,yearSalary=yearSalary,daySalary=daySalary ,hourSalary=hourSalary)

s = SalaryAccount()
print(s(5000)) # 可 以 像 调 用 函 数 一 样 调 用 对 象 的 _ _ c a ll _ _ 方 法

方法没有重载

在其他语言中,可以定义多个重名的方法,只要保证方法签名唯一即可。方法签名包含 3 个部分:方法名、参数数量、参数类型。
Python中,方法的的参数没有声明类型(调用时确定参数的类型),参数的数量也可以由 可变参数控制。因此,Python中是没有方法的重载的。定义一个方法即可有多种调用方式, 相当于实现了其他语言中的方法的重载。
如果我们在类体中定义了多个重名的方法,只有最后一个方法有效。
建议:不要使用重名的方法!Python中方法没有重载。

方法的动态性

Python是动态语言,我们可以动态的为类添加新的方法,或者动态的修改类的已有的方法。

# 测 试 方 法 的 动 态 性 
class Person: 
	def work(self): print("努力上班!")

def play_game(self): 
	print("{0}玩游戏".format(self))
def work2(s): 
	print("好好工作,努力上班!")

Person.play = play_game 
Person.work = work2 
p = Person() 
p.play() 
p.work()

私有属性和私有方法(实现封装)

Python对于类的成员没有严格的访问控制限制,这与其他面向对象语言有区别。关于私有 属性和私有方法,有如下要点:

  1. 通常我们约定,两个下划线开头的属性是私有的(private)。其他为公共的(public)。
  2. 类内部可以访问私有属性(方法)
  3. 类外部不能直接访问私有属性(方法)
  4. 类外部可以通过“_类名__私有属性(方法)名”访问私有属性(方法)

【注】方法本质上也是属性!只不过是可以通过()执行而已。

@property装饰器

@property 可以将一个方法的调用方式变成“属性调用”。
@property 主要用于帮助我们处理属性的读操作、写操作。
这种做法不安全。比如,我需要限制薪水必须为1-10000 的数字。这时候,我们就需要通过getter、setter方法来处理。

# 测 试 
@property 
class Employee:
	def __init__(self,name,salary): 
		self.name = name 
		self.__salary = salary

	@property	# 相 当 于 s a l a r y 属 性 的 g e t t e r 方 法
	def salary(self): 
		print("月薪为{0},年薪为 {1}".format(self.__salary,(12*self.__salary))) 
		return self.__salary;
	
	@salary.setter 
	def salary(self,salary):	# 相 当 于 s a l a r y 属 性 的 s e t t e r 方 法 
		if(0<salary<1000000): 
			self.__salary = salary 
		else: 
			print("薪水录入错误!只能在0-1000000之间")

emp1 = Employee("wps",100) 
print(emp1.salary)
emp1.salary = -200

属性和方法命名总结

· _xxx:保护成员,不能用“frommodule import * ”导入,只有类对象和子类对象能访 问这些成员。 · xxx:系统定义的特殊成员 · __xxx: 类中的私有成员,只有类对象自己能访问,子类对象也不能访问。(但,在类外 部可以通过“对象名._类名__xxx”这种特殊方式访问。 Python 不存在严格意义的私有成员)
注:再次强调,方法和属性都遵循上面的规则。

类编码风格

  1. 类名首字母大写,多个单词之间采用驼峰原则。
  2. 实例名、模块名采用小写,多个单词之间采用下划线隔开。
  3. 每个类,应紧跟“文档字符串”,说明这个类的作用。
  4. 可以用空行组织代码,但不能滥用。在类中,使用一个空行隔开方法;模块中,使用两 个空行隔开多个类。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值