python面向对象编程 -- 基本概念
面向对象的编程简要概括就是将要处理的问题抽象为数据和操作的集合,用类对其进行封装。其中数据和操作都称为类的属性,它们是一般是不变的。
对类进行实例化生成我们所说的对象,对象有自己的属性。对象的属性一般是个性化的,不同的对象可能具有不同的属性。同一个类的所有对象都共享类的属性。
对象属性的查找顺序为:对象自身 --> 类 --> 类的祖先类
在python中一切皆对象。
以下我们讨论python中类相关的概念和语法。
1、类的定义
class ClassName:
<statement-1>
.
.
.
<statement-N>
- 类定义必须使用class关键字
- 类名最好使用大驼峰,如ClassName, 这是一种约定
- 当输入类定义时,一个新的命名空间产生,在类中定义的所有本地变量都放入这个新的命名空间。
- 命名空间中的所有变量都是类的属性。类属性主要分为两类,数据属性(变量)和函数。
- 语句块执行完成后,生成一个类对象绑定到ClassName。ClassName的作用域由它的定义的位置决定。
python中一切皆对象,类也是对象,它是type类的实例。可以用 obj.__class__来查看一个对象是由那个类实例化而来的。
类中可以使用任何合法的语句,不过实际应用中,主要是赋值语句和函数定义。
2、类对象
下面的代码定义了一个 Chinese 类:
class Chinese:
"""A sample example class"""
nationality = 'China' def display(self):
print(self, 'I am Chinese!', sep=', ') for name, value in sorted(Chinese.__dict__.items(), key=lambda x: x[0]):
print(name, '==>', value)
类定义会生成一个新的命名空间,其中包含了所有在类本地定义的变量,也就是类的属性。这些属性可以在类的 __dict__属性中查看,可以将其近似等价于类的命名空间。其中 __name__形式的属性为特殊属性。
print(type(Chinese.__dict__)) # <class 'mappingproxy'>
for name, value in sorted(Chinese.__dict__.items(), key=lambda x: x[0]):
print(name, '==>', value) # __dict__ ==> <attribute '__dict__' of 'Chinese' objects>
# __doc__ ==> A sample example class
# __module__ ==> __main__
# __weakref__ ==> <attribute '__weakref__' of 'Chinese' objects>
# display ==> <function Chinese.display at 0x1020759d8>
# nationality ==> China
- __dict__ 在类定义的时候自动生成。
- __doc__ 类定义的时候自动生成。值为类定义语句块内第一行,类的文档字符串,由三引号引用。如果没有值为None。
- __module__ 类定义所在的模块,自动添加的属性。如果是正在执行的模块,值为 __main__
- __weakref__
- display 和 nationality 用户定义属性
python中属性的引用都是通过obj.name 的形式,name为对象 obj 的属性。类中的所有属性都可以通过obj.name 的形式引用。比如该类的两个用户自定义属性:数据属性 nationality 和 函数 display:
print(Chinese.nationality) # China
print(Chinese.display) # <function Chinese.display at 0x1021759d8>
Chinese.display(1) # 1, I am Chinese!
通过类引用函数并对其进行调用,与普通的函数调用没有差异。不过,在类中定义的函数一般是给实例使用的,不建议直接通过类引用,下面会进一步说明。
3、类实例化
类的实例化使用和函数调用类似的语法。
xm = Chinese()
上面的语句创建了一个新的Chinese类的实例,并将其赋值给 xm 变量。实例有自己的命名空间:
print(xm.__dict__) # {}
可以看到 xm.__dict__ 的返回值是一个空字典,实例 xm没有自己的属性。可以直接通过 xm.name = 'xiaoming' 的形式为实例添加属性。也可以通过 del xm.name 删除该属性:
xm.name = 'xiaoming'
print(xm.__dict__) # {'name': 'xiaoming'}
del xm.name
print(xm.__dict__) # {}
如果类的所有实例都具有某些属性,只是属性的值不同,可以通过定义实例的初始化方法,在方法中为实例添加属性。
3.1 初始化方法
类的实例化过程:
- 实例化出一个对象
- 自动调用特殊方法 __init__对产生的对象初始化。如果类中没有定义会在父类(父类的概念之后说明)中查找该方法。
我们称__init__方法为实例的初始化方法, __init__方法中不要写返回值,默认返回None。
一般在实例初始化方法中会定义实例的个性化属性,这些属性是实例私有的,可以通过实例的__dict__属性查看。实例的属性不会影响类的属性,换句话说类不能引用实例的属性。
下面是对Chinese类的扩展:
class Chinese:
"""A sample example class"""
nationality = 'China' def __init__(self, name, age, gender):
self.name = name
self.age = age
self.gender = gender def display(self):
print(self, 'I am Chinese!', sep=', ') xm = Chinese('xiaoming', 18, 'male')
print(xm.__dict__) # {'name': 'xiaoming', 'gender': 'male', 'age': 18}
print(Chinese.__dict__.keys())
# dict_keys(['__weakref__', '__module__', '__dict__', '__init__', 'nationality', 'display', '__doc__'])
self指代引用该方法的实例(具体实现在4.1介绍),实例化操作的参数列表化传递给__init__方法,Chinese('xiaoming', 18, 'male') --> xm.__init__('xiaoming', 18, 'male')
3.2 实例的类
查看对象的类:
- obj.__class__
- type(obj)
print(xm.__class__)
print(type(xm))
# <class '__main__.Chinese'>
# <class '__main__.Chinese'>
判断一个对象是不是某个类的实例:isinstance(obj, ClassName)
print(isinstance(xm, Chinese))
# True
4 实例
实例可以操作两种属性:数据属性和方法
print(xm.name, xm.age, xm.gender, sep=', ') # xiaoming, 18, male
print(xm.nationality, xm.display, sep=', ')
# China, <bound method Chinese.display of <__main__.Chinese object at 0x10217c898>>
有上面的代码可以看到实例不仅可以引用自己的属性,也可以引用类的属性。类属性可以被它的实例共享。
值得注意的是,实例对类的函数的引用。其返回值并不是一个函数对象而是一个"bound method"绑定的方法对象。尝试调用这个对象:
xm.display(1)
# Traceback (most recent call last):
# File "test.py", line 28, in <module>
# xm.display(1)
# TypeError: display() takes 1 positional argument but 2 were given
xm.display() # <__main__.Chinese object at 0x10217c7f0>, I am Chinese!
display函数要求传入一个位置参数,第1行给方法传入一个参数1,调用出错,错误信息告诉我们多传入了一个位置参数。
再次调用,不传参,竟然能够正常调用了!why?函数打印了传入的值,"<__main__.Chinese object at 0x10217c7f0>",表明出入的是一个Chinese对象,在本例中只能是 xm。这是怎么实现的呢?
4.1 实例方法
print(Chinese.display)
print(xm.display)
print(Chinese.display is xm.display) # <function Chinese.display at 0x1021759d8>
# <bound method Chinese.display of <__main__.Chinese object at 0x10217c7f0>>
# False
分别通过类和实例引用display属性,返回的并不是同一个对象:通过类引用返回一个函数对象;通过实例引用返回一个"bound method"绑定的方法对象。
- 方法:属于某个对象的函数。当通过对象(实例)引用一个类的属性,且该属性对应一个函数对象时,函数和实例绑定返回一个方法对象。可以通过方法对象的__self__ 和 __func__ 属性查看对应的实例和方法
method = xm.display
print(method.__self__) # <__main__.Chinese object at 0x10217c7f0>
print(method.__func__) # <function Chinese.display at 0x1021759d8> - 方法对象是可调用的,方法的调用即其对应的类的函数属性的调用,特殊之处在于会将其实例作为第一个参数传给函数,等价形式为:method(*args, **kwargs) ==> method.__func__(method.__self__, **args, **kwargs)。在本例中xm.display() 等价于Chinese.display(xm)。简要概括来说就是,方法对应函数的第一个参数由python自动填充以引用实例对象。
- 在类中定义的函数一般至少有一个位置参数,第一个位置参数一般用'self'标识,指代引用函数的实例。这是一个约定,可以用任意其他合法标识符替代,为了代码的可读性,不建议这么做。
- 类中定义的函数对应到实例即为实例的方法。
很多资料中将类中的定义的函数都称为方法,虽然如此我们要知道未经过任何装饰器装饰的普通函数本质上依然是函数,只有在通过实例引用是才与实例绑定生成方法对象。
以上是相关的基本概念,下一篇讨论类的封装、继承相关的概念。
python面向对象编程 -- 基本概念的更多相关文章
- python面向对象编程学习
python面向对象编程 基本概念理解 面向对象编程--Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作 ...
- python 面向对象编程(一)
一.如何定义一个类 在进行python面向对象编程之前,先来了解几个术语:类,类对象,实例对象,属性,函数和方法. 类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义: class c ...
- python面向对象编程进阶
python面向对象编程进阶 一.isinstance(obj,cls)和issubclass(sub,super) isinstance(obj,cls)检查是否obj是否是类 cls 的对象 1 ...
- Python面向对象编程——继承与派生
Python面向对象编程--继承与派生 一.初始继承 1.什么是继承 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题. 继承是一种创 ...
- 图解python | 面向对象编程
作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/56 本文地址:http://www.showmeai.tech/article-det ...
- python 面向对象编程学习
1. 问题:将所有代码放入一个py文件:无法维护 方案:如果将代码才分放到多个py文件,好处: 1. 同一个名字的变量互相不影响 2.易于维护 3.引用模块: import module 2.包:解决 ...
- Python面向对象编程指南
Python面向对象编程指南(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1SbD4gum4yGcUruH9icTPCQ 提取码:fzk5 复制这段内容后打开百度网 ...
- Python面向对象编程(下)
本文主要通过几个实例介绍Python面向对象编程中的封装.继承.多态三大特性. 封装性 我们还是继续来看下上文中的例子,使用Student类创建一个对象,并修改对象的属性.代码如下: #-*- cod ...
- Python 面向对象编程——访问限制
<无访问限制的对象> 在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑.但是,从前面Student类的定义来看(见:Py ...
随机推荐
- python爬虫之git的使用
一.简单认识: 1.初始化文件夹为版本控制文件夹,首先建立一个文件夹,进入这个文件夹以后输入git init初始化这个文件夹. 2.Git几种位置概念 1.本地代码:本地更改完代码以后,虽然是存放在g ...
- JavaScript中forEach与each
forEach是ES5中操作数组的一种方法,主要功能是遍历数组,例如: var arr = [1,2,3,4]; arr.forEach(alert); 等价于: var arr = [1, 2, 3 ...
- WPF程序中App.Config文件的读与写
WPF程序中的App.Config文件是我们应用程序中经常使用的一种配置文件,System.Configuration.dll文件中提供了大量的读写的配置,所以它是一种高效的程序配置方式,那么今天我就 ...
- Algorithm Visualizer
Algorithm Visualizer https://algorithm-visualizer.org/ https://algorithm-visualizer.org/divide-and-c ...
- JMeter 连接 sql server
1.安装驱动 http://www.microsoft.com/zh-CN/download/details.aspx?id=11774 下载后解压后复制sqljdbc.jar到 “jmeter的安装 ...
- WEB相关概念、Tomcat初识、Servlet、基本知识。
/* * 一.web的概念? * 1.web就是在http协议基础之上, 利用浏览器进行访问的网站. * Web Page指网站内的网页. 我们常说的WWW(World Wide Web 万维网)就是 ...
- 四、K8S
一.查看日志 journalctl -xeu kubelet
- Spring Boot 构建电商基础秒杀项目 (五) 用户注册
SpringBoot构建电商基础秒杀项目 学习笔记 UserService 添加 void register(UserModel userModel) throws BusinessException ...
- codeforces472C
Design Tutorial: Make It Nondeterministic CodeForces - 472C A way to make a new task is to make it n ...
- python数据类型知识整理
python数据类型种类 int数字.bool布尔值.dict字典.tunple元组.set集合.list列表.字符串 int数字 #常用来进制转换 num = 11 #转化成2进制 bin_num ...