什么是类

百度百科:

类是对象的抽象,对象是对客观事物的抽象。

用通俗的话来说:

类是类别的意思,是数据类型。
对象是类别下的具体事物。

也就是说:

类是数据类型,对象是变量。

比如:

自定义一种数据类型:水果。那水果就是类。
由此数据类型创建一个变量:一个苹果。那这个苹果就是对象。
类是抽象的,对象是具体的。

类和对象的关系

类是一种数据类型,相当于一个模板,用于创建对象。
每一个对象都有自己独立的内存空间,用于存储数据成员。

比如:

人都有名字,年龄,性别等信息。这是一个类,是抽象的。
小明叫张明,18岁,男。这是一个对象,是具体的。

专业术语

封装了变量和函数的一种自定义的数据类型

  • 数据成员

类中的变量

  • 方法

类中的函数

  • 对象

由类创建的变量称作为对象

  • 实例化

创建一个对象。
因为类是抽象的,而对象是具体的,是一个实例,所以通过类创建对象的过程称为实例化。

  • 继承

根据父类创建子类,子类 继承 父类中所有变量和方法

数据成员

示例:

class Student:      #定义类
pass
s=Student() #创建对象(类的实例化)
s.i=12345 #创建或修改类的数据成员
print(s.i) #访问类的数据成员

结果:

12345

解释:

使用关键字class定义一个类
类名为Student,通常类名首字母大写。
对象名为s
i 为数据成员
访问类中成员的语法:对象名.成员名

每个对象都有单独的内存空间去存储自己的普通数据成员(后面会讲到静态数据成员,就不一样了)

方法

类中的函数称为方法
方法可以访问此类所有的数据成员和方法。

示例:

class Student:
def f(self): #定义方法
print("hello world")
s=Student() #创建对象(类的实例化)
s.f() #调用类的方法

结果:

hello world

解释:

f 为方法名
访问类中成员的语法:对象名.成员名
类的方法与普通的函数区别:第一个参数为self。
self实际上是对象的地址。所以通过self访问的成员都属于当前对象。

带有参数的方法:

class Student:
def f(self,s): #定义方法
print(s)
s=Student()
s.f("hello world") #调用类的方法 (输出:hello world)

解释:

字符串hello world将传给s

self

示例:

class Student:
def f(self):
print(self.i) #访问类中的属性
s=Student()
s.i=12345
s.f()

结果:

12345

解释:

类的方法与普通的函数区别:第一个参数为self。
self实际上是对象的地址。
每一个对象的self地址都不一样,它们都指向本身。
通过self可以访问自身的数据成员和方法。

访问数据成员和方法必须使用self,否则就是临时变量,而不是数据成员

示例:

class Student:
def f(self):
i=200 #临时变量
print(self.i) #数据成员
print(i)
s=Student()
s.i=100 #创建类的普通数据成员
s.f()

结果:

100
200

解释:

通过结果可以看出,两个i是不同的变量
通过self访问的是对象内部的内存空间,是当前对象的成员。

构造方法

构造方法:创建对象时自动调用此方法

class Student:
def __init__(self):
print("对象被创建")
s=Student()

结果:

对象被创建

数据成员

普通数据成员

普通数据成员存储在对象自己的内存空间中。
所以每个对象的普通数据成员都是独立的,因为它们的内存空间不一样。

示例:

class Student:
def f(self):
print(self.i) #在类中访问普通数据成员
s=Student()
s.i=100 #创建类的普通数据成员
s.i=200 #修改类的普通数据成员
print(s.i) #访问类的普通数据成员
s.f()

解释:

当数据成员不存在时, s.i=100将创建此数据成员

当数据成员存在时,s.i=100将修改此数据成员

self是对象的地址,用于访问对象自己的属性,包括数据成员和方法

一般在构造函数中创建普通数据成员

在构造函数中创建普通数据成员:

class Student:
def __init(self):
self.a=1 #定义普通数据成员
self.b=2 #定义普通数据成员

解释:

当创建对象时会自动调用构造方法,所以数据成员也被自动创建。
若不使用构造方法,需要在手动的、依次给每一个对象创建这些数据成员。(很麻烦)

静态数据成员

静态数据成员存储在类中,是所有对象共享的。
通过类名访问静态成员,而不是对象名。

示例:

class Student:
name="张三"
print(Student.name) #访问静态数据成员
Student.name="李四" #修改静态数据成员

解释:

静态数据成员在类中直接定义
通过类名访问静态数据成员,因为是共享的
通过对象名访问普通数据成员,因为每个对象之间是独立的

注意:也可以通过对象名访问静态数据成员,但不建议这样

class Student:
name="张三"
s1=Student()
s2=Student() print("----创建之前:----")
print("Student.name :",Student.name)
print("s1.name :",s1.name) print("----创建之后:----")
s1.name="李四"
print("Student.name :",Student.name)
print("s1.name :",s1.name)

结果:

----创建之前:----
Student.name : 张三
s1.name : 张三
----创建之后:----
Student.name : 张三
s1.name : 李四

解释:

可以看到,当没有创建普通数据成员时:s1.name表现为静态数据成员

当创建普通数据成员后:
s1.name表现为普通数据成员

得出结论:不建议用对象名去修改静态数据成员

私有数据成员

私有数据成员只能被当前类所访问,外部和子类中都无法访问。
这样做的是为了数据和代码安全。

示例:

class Student:
__name="张三" #创建类的静态私有数据成员
def __init__(self):
self.__age=18 #创建私有数据成员
s=Student()

解释:

若在类的外部访问类的私有成员,则会报错:AttributeError。
私有数据成员名:使用双下划线开头。
静态私有数据成员:私有的,所有对象共享的通过类名访问

外部和子类中都无法访问私有成员,那如何访问它们呢?借助类中非私有方法作为桥梁

class Student:
def __init__(self):
self.__name="张三"
def getName(self): #通过此方法访问静态成员__name
return self.__name
def setName(self,name): #通过此方法修改静态成员__name
self.__name=name
s=Student()
s.setName("李四")
print(s.getName()) #输出:李四

解释:

无法直接访问私有数据成员
类的内部可以访问私有数据成员。如非私有方法。
得出结论:通过非私有方法间接访问私有数据成员。

特殊的数据成员

这些特殊的数据成员已经存在,无需自己创建
如__dict__将会返回类中所有的数据成员,以字典返回

class Student:
def __init__(self):
self.a=1
self.b=2
s=Student()
print(s.__dict__) #输出{'a': 1, 'b': 2}

方法

普通方法

class Student:
def show(self,s):
print("我是"+s)
s=Student()
s.show("学生") #输出:我是学生

私有方法

在类的外部和子类中无法访问私有方法
私有方法仅供内部使用
私有方法名用双下划线开头

class Student:
def __show(self): #外部无法直接访问
print("Private")
s=Student()
s.__show() #外部无法访问私有方法,报错!!!!

静态方法

静态方法是共享的,属于类,而不是某个对象
静态方法只能访问静态数据成员

class Student:
@classmethod
def show(cls,s):
print(cls,s) #输出类名
Student.show("张三") #输出:<class '__main__.Student'> 张三

解释:

方法前的@classmethod表示:此方法为静态方法

与普通方法类似,有一个额外的参数cls,cls是class的缩写,代表类的地址。

因为静态方法是共享的,所以通过类名调用静态方法。

构造方法

创建对象时Python自动调用构造方法

通常在构造方法中做对象的初始化工作,如创建数据成员。

构造方法名固定为__init__。

class Student:
def __init__(self):
self.name=""
self.age=0
s=Student()

析构方法

回收对象时Python自动调用析构方法
通常在析构方法中做对象的收尾工作,如关闭打开的文件。

class Student:
def __del__(self):
print("对象已被删除")
s=Student()
对象已被删除

解释:

析构方法名固定为__del__。

程序运行完毕时会回收所有变量和内存空间,所以会删除对象s。

除此之外,代码块运行完毕也会回收临时变量,如函数中的临时变量。

__call__方法

__call__方法:对象名可以当作方法名使用,调用__call__方法的函数体和形参

class Student:
def __call__(self):
print("调用__call__")
s=Student()
s() #输出:调用__call__

解释:

可以看到__call__方法的调用方式不是s.__call__(),而是通过对象名调用s()

强制转换

通过定义强制转换的方法,可以将对象转换成任意数据类型。

class Student:
def __int__(self):
return 18
s=Student()
a=int(s) #a的值为18

解释:

若要转换为int,需要定义__int__方法
强制转换的语法为int(obj)

若要转换为其他类型,如float,需要定义__float__方法。

应用-得到学生的成绩
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def __int__(self):
return self.age
s=Student("张三",20)
a=int(s) #得到学生s的年龄
应用-得到学生的信息
class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def __str__(self):
return "我是一名学生,姓名:%s,年龄:%d"%(self.name,self.age)
s=Student("张三",20)
print(s) #直接输出,就会调用str(obj)

结果:

我是一名学生,姓名:张三,年龄:20

解释:

类似的还有float等数据类型,也都可以做强制转换
若要转换为其他类型,如float,需要定义__float__方法。

运算符重载

对象之间可以进行加减乘除等操作,如:

s1=Student()
s2=Student()
s3=s1-s2

那s3的值到底是多少?到底是s1和s2身高差?还是平均分差?还是其他属性的差值?
这需要我们自己来定义,进行运算符的重载。

示例-重载符号+:

class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def __add__(self,other): #运算符重载
return self.age + other.age
s1=Student("张三",20)
s2=Student("李四",18)
print(s1+s2) #输出38 (20+18=38)

解释:

重载符号+的方法名固定为:add
参数固定为self和other,分别表示左操作数和右操作数。
通过return得到结果。

常用的符号与方法名

符号 方法名 描述
+ __add__
- __sub__
* __mul__
/ __truediv__
// __floordiv__ 整除
% __mod__ 取模
** __pow__
下标运算符重载

通过下标运算符,可通过obj[n]这种形式访问对象中的数据

示例-通过下标查询:

class Student:
def __init__(self,name,age):
self.name=name
self.age=age
def __getitem__(self, item): # 使用obj[n]时调用
if type(item) == slice: #切片
print(item.start) #开始下标
print(item.stop) #结束下标
print(item.step) #步长
return item
s1=Student("张三",20)
print(s1[1:8:7])

结果:

1
8
7
slice(1, 8, 7)

示例-通过下标修改:

class Student:
def __init__(self):
self.score={"语文":98,"数学":96}
def __setitem__(self, key, value):
self.score[key]=value
s1=Student()
s1["语文"]=100
print(s1.score)

结果:

{'语文': 100, '数学': 96}

示例-通过下标删除:

class Student:
def __init__(self):
self.score={"语文":98,"数学":96}
def __delitem__(self, key):
del self.score[key]
s1=Student()
del s1["语文"]
print(s1.score)

结果:

{'数学': 96}

属性

通过定义属性,可以把函数变成数据成员

示例:

class Student:
@property
def name(self): #调用方式print(obj.name)
return "张三"
@name.setter
def name(self, value): #调用方式obj.name="Fei"
print(value)
@name.deleter
def name(self): #调用方式del obj.name
print("del name")
s=Student()
print(s.name) #输出:张三
s.name="李四" #输出:李四
del s.name #输出:del name

解释:

使用@property将函数变成数据成员
name.setter:name()的set函数
name.deleter:name()的del函数
属性就像数据成员一样使用,实际上是函数


继承

当我们想为某个类添加新的方法时,无需重新定义所有方法,使用继承即可。
例如:普通学生可以得到成绩信息,艺术生还能得到艺术成绩。

好处:

代码重用,方便维护。
通过继承,可以得到所有父类的方法,不必再复制一份代码。

基类&派生类

已存在的类称为基类(父类),新建的类称为派生类(子类)。

注意点:

子类不能直接访问父类的私有成员

示例:

class A:
def show(self):
print("我是函数show()")
class B(A): #继承了A
pass
b=B()
b.show() #因为B继承了A,所以b拥有函数show()

解释:

C继承了A和B,所以拥有A和B的所有方法
子类不能直接调用父类的私有成员

多重继承

子类可以再被继承。
如:A被B继承,B又被C继承。

class A:
pass
class B(A): #继承了A
pass
class C(B): #继承了B
pass
c=C()

函数重写

继承父类的函数之后,可以设置同名函数,这是新函数会把旧函数覆盖。

class A:
def show(self):
print("我是A")
class B(A):
def show(self): #重写了show函数
print("我是B")
b=B()
b.show() #输出:我是B

06-Python类与对象的更多相关文章

  1. python类与对象各个算数运算魔法方法总结

    1.python类与对象各个算术运算魔法方法总结: 2.各个魔法方法应用举例: 3.实例训练: (1)我们都知道在 Python 中,两个字符串相加会自动拼接字符串,但遗憾的是两个字符串相减却抛出异常 ...

  2. python 类和对象的属性

    python类和对象的属性分为类属性和对象属性两大类,类属性属于类,而对象属性属于对象. 1. 父类的对象属性会被子类的对象继承. 2. 父类的类属性会被子类继承,还是作为类属性,如果父类改变了类属性 ...

  3. 一文讲全了Python 类和对象内容

    摘要:这是一个关于 Python 类和对象的全部内容. 本文分享自华为云社区<从零开始学python | Python 类和对象-面向对象编程>,原文作者:Yuchuan  . Pytho ...

  4. python类、对象

    python类.对象 学习完本篇,你将会深入掌握 什么是类,对象 了解类和对象之间的关系 能独立创建一个People(人类),属性有姓名.性别.年龄.提供一个有参的构造方法,编写一个show方法,输出 ...

  5. python 类、对象、方法、属性

    在python中,一个对象的特征也称为属性(attribute).它所具有的行为也称为方法(method) 结论:对象=属性+方法 在python中,把具有相同属性和方法的对象归为一个类(class) ...

  6. python类、对象、方法、属性之类与对象笔记

    python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性(特征)和行为来描述一个对象的.比如家里的小狗, ...

  7. python类与对象基本语法

    面向对象编程的2个非常重要的概念:类和对象. 对象是面向对象编程的核心,在使用对象的过程中,为了将具有共同特征和行为的一组对象抽象定义,提出了另外一个新的概念--类. 类就相当于制造飞机时的图纸,用它 ...

  8. python 类和对象

    类和对象 类 1.类的组成    数据和函数,二者是类的属性 2.两个作用: 实例化 属性引用  属性引用:类名.属性(增删改查)   实例化: 类名加括号就是实例化,会自动出发__init__的运行 ...

  9. Python类和对象

    目录 类与对象 其他方法 继承 经典类和新式类 派生 组合 接口.归一化设计与抽象类 继承实现的原理 子类中调用父类的方法 指名道姓 super()方法 多态与多态性 封装 单下划线开头 双下划线开头 ...

  10. python类与对象的组合与继承

    1.把类的对象实例化放到一个新的类里面叫做类的组合,组合就是指几个横向关系的类放在一起,纵向关系的类放在一起是继承,根据实际应用场景确定.简单的说,组合用于“有一个”的场景中,继承用于“是一个”的场景 ...

随机推荐

  1. dotnet 6 通过 DOTNET_ROOT 让调起的应用的进程拿到共享的运行时文件夹

    我的应用是独立发布的,在用户的设备上不需要额外去安装 .NET 运行时.但是我的应用有一个需求是下载另一个应用作为插件,由本应用调起插件进程.本文告诉大家如何解决调用插件的进程时,赋值给插件进程运行时 ...

  2. 迁移 dotnet 6 提示必须将目标平台设置为 Windows 平台

    我在迁移一个古老的项目为 .NET 6 框架,但是 VS 提示 error NETSDK1136 如果使用 Windows 窗体或 WPF,或者引用使用 Windows 窗体或 WPF 的项目或包,则 ...

  3. 阿里云OSS文件上传几种方法(主要是前端)

    目录 零.准备 一.服务端签名后直传 1. 阿里云控制台配置 2. 后端接口开发(PHP) 3. 前端获取签名后上传 二.使用STS临时凭证进行上传 1. 后端接口开发(node) 2. 前端获取临时 ...

  4. 04 Xpath_[实例]爬取maoyan

    目录 Xpath lxml库的安装和使用 提取的内容 代码 生成的csv 下载的图片 参考文档 Xpath lxml库的安装和使用 提取的内容 随意选取的一段 节点包含的影片信息,如下所示: < ...

  5. Xcode多进程调试:WKWebView

    由于WKWebView使用的是多线程架构,渲染模块和网络模块都各自在一个单独的进程里面,因此,如果需要设置渲染模块或者网络模块里面的断点,需要做一些特殊处理. 举个例子,假设在Xcode里面设置了渲染 ...

  6. postgresql 开启审计日志

    1.审计清单说明 logging_collector     --是否开启日志收集开关,默认off,推荐on log_destination       --日志记录类型,默认是stderr,只记录错 ...

  7. leaflet 使用高德地图实例

    let map = L.map("mapid", { minZoom: 10, maxZoom: 15, center: [37.005646, 114.52044], zoom: ...

  8. 卷爆短剧出海:五大关键,由AIGC重构

    短剧高温下,谈谈AIGC的助攻路线. 短剧,一个席卷全球的高温赛道. 以往只是踏着霸总题材,如今,内容循着精品化.IP化的自然发展风向,给内容.制作.平台等产业全链都带来新机,也让短剧消费走向文化深处 ...

  9. Python OpenCV #1 - OpenCV介绍

    一.OpenCV介绍 1.1 OpenCV-Python教程简介 OpenCV由 Gary Bradsky 于1999年在英特尔创立,第一个版本于2000年发布. Vadim Pisarevsky 加 ...

  10. 简单粗暴通过 Binlog 日志来恢复 MySQL 数据

    引言 Binlog 日志的主要作用: 1.增量备份. 2.主从复制. 操作步骤 1.登录 MySQL -> 执行 show variables like '%log_bin%'; 查询 binl ...