当前位置: 首页 > 编程日记 > 正文

【Python】解析Python中类的使用

目录结构:

contents structure [-]
  1. 类的基本使用
  2. 专有方法
  3. 继承
    1. 单重继承
    2. 多重继承
    3. 砖石继承

1.类的基本使用

下面是类使用的一个简单案例,

class person:"person 类的描述信息"def __init__(self,name="",age=0):self.name = nameself.age = agedef setName(self,name):'''设置名称'''self.name = namedef getName(self):'''获取名称'''return self.namedef setAge(self,age):self.age = agedef getAge(self):return self.agedef __del__(self):print("person (name:"+self.name+",age:"+str(self.age)+") is deleting")p = person("jame",12);
#Output:jame
print(p.getName())
#效果和下面的调用方式是一样的
#person.getName(p)#Output:12
print(p.getAge())
#效果和下面的调用方式是一样的
#person.getAge(self)#Output: person 类的描述信息
print(p.__doc__)#输出person类的帮助信息
print(help(person))del p

输出:

jame
12
person (name:jame,age:12) is deleting
person 类的描述信息
Help on class person in module __main__:class person(builtins.object)|  person 类的描述信息|  |  Methods defined here:|  
...


__init__函数是构造函数,在构造对象的时候会自动调用该函数。
__del__函数是析构函数,在使用del删除目标对象时会自动调用该方法。

Python中,类不可以定义多个构造方法,只能定义一个构造方法。所有成员实例函数的第一个参数都必须是self参数(也可以有非self参数的成员函数,下面会讲解)。python会自动创建成员属性,无需提前定义,例如self.name=name。

类属性

类属性的定义无需使用self参数,可以直接定义到类中。类属性可以直接通过类名调用。

class Person:type = "哺乳类"def __init__(self,name,age):self.name = nameself.age = agep = Person("luyis",13)
#通过类名调用类属性
print(Person.type)
#通过对象调用类属性
print(p.type)

静态方法

静态方法是类中的函数,不需要实例。静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,但是和类本身没有交互,即在静态方法中,不会涉及到类中的方法和属性的操作。用 @staticmethod 装饰的不带 self 参数的方法,类的静态方法可以没有参数,可以直接使用类名调用。

import time
class TimeTest:def __init__(self):pass#静态方法
    @staticmethoddef show_time():print(time.strftime("%H:%M:%S", time.localtime()))TimeTest.show_time()

类方法

类方法是将类本身作为对象进行操作的方法。默认有个 cls 参数,可以被类和对象调用,需要加上 @classmethod 装饰器。

class ClassTest:num = 0def __init__(self,num):ClassTest.num = num#类方法
    @classmethoddef showNum(cls):print(cls.num)c = ClassTest(20)
#通过类直接调用
ClassTest.showNum()
#通过实例对象调用
c.showNum()

私有成员

Python中的私有成员,不能在类外面直接访问。私有成员只需要在成员前面加上两条下划线(__)就表明该成员是私有的了。

class Person:#__type是私有成员__type = "哺乳类"def __init__(self,name="",age=0,country="中国"):#__name,__age是私有成员self.__name = nameself.__age = ageself.__setcountry(country)def get_name(self):return self.__namedef get_age(self):return self.__agedef set_name(self,name):self.__name = namedef set_age(self,age):self.__age = age#__setcountry是私有函数def __setcountry(self,cty):self.country = cty@classmethoddef get_type(cls):return cls.__type@classmethoddef set_type(cls,type):cls.__type = typep = Person("jame",21)
print(p.get_name())
print(p.get_age())
print("--------------------")p.set_name("charlse")
p.set_age(31)
print(p.get_name())
print(p.get_age())
print("-------------------")print(Person.get_type())
print("------------------")Person.set_type("灵长类")
print(Person.get_type())

输出:

jame
21
--------------------
charlse
31
-------------------
哺乳类
------------------
灵长类


定义私有成员的格式:
__xxx:私有成员,只有类对象自己能访问,子类对象不能直接访问到这个成员,

注意:虽然不能在类外直接访问到类的私有成员,但在对象外部可以通过“ 对象名._类名__xxx ”这样的特殊方式来访问类的私有成员。应此,在Python中不存在严格意义上的私有成员。

class Person:#__type是私有成员__type = "哺乳类"def __init__(self,name="",age=0):#__name,__age是私有成员self.__name = nameself.__age = agep = Person("Emma",32);
#直接访问私有成员的值
print(p._Person__type)
print(p._Person__name)
print(p._Person__age)#直接修改私有成员的值
p._Person__age = 33
p._Person__name = "Angela"
p._Person__type = "灵长类"print("-------------------")
print(p._Person__type)
print(p._Person__name)
print(p._Person__age)

输出:

哺乳类
Emma
32
-------------------
灵长类
Angela
33

2.专有方法

Python除了自定义私有变量和方法外,还可以定义专有方法。专有方法是在特殊情况下或使用特殊语法时由python调用的,而不是像普通方法一样在代码中直接调用。看到形如__XXX__的变量或函数名时就需要注意下,这在python中是有特殊用途的,下面是Python中的部分专用方法:
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__str__: 打印,转换,适合于展示给用户看的
__repr__ : 打印,转换,适合开发者调试
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__call__: 函数调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__div__: 除运算
__mod__: 求余运算
__pow__: 乘方
__doc__: 说明文档信息

上面笔者已经讲解过__init__和__del__函数的使用了,应此笔者不再这里重复缀述了。笔者接下来讲解其它的专有方法的用法:

__str__,__repr__

都是用于将对象转化为字符串的内置方法。
但是 repr() 函数将对象转化为供解释器读取的形式,__str__只是覆盖了__repr__以得到更友好的用户显示。
例如:

>>> y = 'a string'
>>> repr(y)
"'a string'"
>>> str(y)
'a string'


repr函数的返回字符串可以再次传递给eval函数。但是str函数的返回值传递给eval显然是不合适。

>>> y == eval(repr(y))
True
>>> y == eval(str(y))
Traceback (most recent call last):File "<stdin>", line 1, in <module>File "<string>", line 1a string^
SyntaxError: unexpected EOF while parsing



repr返回的字符串应该是编译器能够再次解析的,str返回的字符串应该可以是易阅读的

在知道了repr和str的区别后,我们就知道该如何自定义__repr__和__str__函数了。

class person:def __init__(self,name="",age=0):self.__name = nameself.__age = agedef __str__(self):return "name:%s,age:%d"%(self.__name,self.__age)def __repr__(self):return "person(name='%s',age=%d)"%(self.__name,self.__age)p = person("jame",12)
#Output: name:jame,age=12
print(str(p))#same as print(p)#Output: person(name='jame',age=12)
print(repr(p))p2 = eval(repr(p))   
#Output: name:jame,age=12
print(p2)

__setitem__,__getitem__

用于通过下标来设置和获取值,可以直接使用[]符来操作。

class DicDecorate:def __init__(self,dic):self.__dic = dicdef __getitem__(self,key):return self.__dic[key]def __setitem__(self,key,val):self.__dic[key] = valdicdec = DicDecorate({})dicdec[0] = "hello"
dicdec[1] = "word"print(dicdec[0])
print(dicdec[1])

__len__():

当调用len函数时会调用该方法。

lass DicDecorate:def __init__(self,dic):self.__dic = dicdef __len__(self):return len(self.__dic);dicdec = DicDecorate({})
print(len(dicdec))

__call__()

关于 __call__ 方法,不得不先提到一个概念,就是可调用对象(callable),我们平时自定义的函数、内置函数和类都属于可调用对象,但凡是可以把一对括号()应用到某个对象身上都可称之为可调用对象,判断对象是否为可调用对象可以用函数 callable。

如果在类中实现了 __call__ 方法,那么实例对象也将成为一个可调用对象。

class Entity:def __init__(self, x, y):self.x, self.y = x, ydef __call__(self, x, y):self.x, self.y = x, ydef __str__(self):return "x=%s,y=%s"%(self.x,self.y)e = Entity(2, 3) # 创建实例
if(callable(e)):e(4, 5) #实例可以象函数那样执行,并传入x y值,修改对象的x y
#Output:x=4,y=5
print(e)


__add__: 加运算 __sub__: 减运算 __mul__: 乘运算 __div__: 除运算 __mod__: 求余运算 __pow__: 幂运算

class Vector:def __init__(self, a, b):self.a = aself.b = bdef __str__(self):return 'Vector (%d, %d)' % (self.a, self.b)def __add__(self,other):return Vector(self.a + other.a, self.b + other.b)v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)

3. 继承

3.1 单重继承

Python继承的语法格式:

class ClassName1(ClassName2):statement

其中
ClassName1:派生类
ClassName2:基类

class Shape:def __init__(self,type,area):self.type = typeself.area = areadef describe(self):return "Share type:%s,area=%f"%(self.type,self.area)
class Square(Shape):def __init__(self,area):super().__init__("square",area);
square = Square(12.1)
print(square.describe())

和其它编程语言一样,可以重写父类中的方法,可以继承父类中开放的属性和方法(不能继承父类中的私有属性和方法)。

3.2 多重继承

除了单重继承,Python还支持多重继承

class ClassName1(ClassName2,ClassName3,ClassName4...):statement

Python多重继承中顺序继承是一个非常重要的概念,如果继承的多个父类中有相同的方法名,但在派生类中使用时未指定父类名,则Python解释器将从左至右搜索,即调用先继承的类中的同名方法。

class A:def test(self):print("I am in Class A");
class B:def test(self):print("I am in Class B");class C(A,B):def __call__(self):#调用A类中的test方法
        self.test()#可以通过类名显示指定调用B类中的test方法
        B.test(self)class D(B,A):def __call__(self):#调用B类的test方法
        self.test()#通过类名显示指定要调用A类中的test方法
    A.test(self)c = C()
c()
print("---------------");
d = D()
d()

输出:

I am in Class A
I am in Class B
-----------------
I am in Class B
I am in Class A

通过上面的结果可以看出,子类在父类中查找方法的顺序是从左到右的。

3.3 砖石继承

砖石继承问题是Python多重继承中的典型问题,下面先通过一张图片看看什么是砖石继承。


通过这张图片看出,D继承了B和C,B和C又派生于A,在调用D类的test()方法时,会再去调用B和C的test()方法,B和C又会去调用A的test()方法,所以A类的test()方法在理论应该会被调用两次,例如:

class A:def test(self):print("I am in Class A");
class B(A):def test(self):A.test(self);print("I am in Class B")
class C(A):def test(self):A.test(self);print("I am in Class C");class D(B,C):def test(self):B.test(self)C.test(self)print("I am in Class D")d = D()
d.test()

输出:

I am in Class A
I am in Class B
I am in Class A
I am in Class C
I am in Class D


从上面的输出结果可以看出,A类的test()被调用了两次。在有些情况这种逻辑将会造成极大的Bug,比如一笔银行转账记录转了两次。要避免这种情况,可以使用super()方法,当使用super()调用父类的test方法时,会转而去调用下一个重写了该super类的test方法,若没有的话才会去调用父类的test方法。
案例:

class A:def test(self):print("I am in Class A")
class B(A):def test(self):super().test() #不能替换为A.test(self)print("I am in Class B")
class C(A):def test(self):super().test()print("I am in Class C")class D(B,C):def test(self):super().test() #可以替换为B.test(self)print("I am in Class D")d = D()
d.test()

输出:

I am in Class A
I am in Class C
I am in Class B
I am in Class D


通过上面的结果我们可以看出,super.test()和父类.test(self)是不一样的,在B类中使用super()调用父类的test()时,会去寻找B实例后的下一个类是否重写A类的test()方法,由于类D继承了类B和类C,所以类C在类B后,而且类C又重写了test()方法,应此会直接调用类C的test()方法。在类C的test()方法中,又使用了super().test()调用父类的test(),所以又会去寻找C实例后的下一个类有重写A类的test方法,因为类D只继承了B和C,并且类C是最后一个,所以C后没有实例直接重写A类的test()方法,因此直接去调用A类的test()方法。最终完整的方法压栈顺序是D->B->C->A。

下面的逻辑和上面案例中使用super()的逻辑是等同的:

class A:def test(self):print("I am in Class A")
class B(A):def test(self):C.test(self)#调用C
class C(A):def test(self):A.test(self)#调用A
class D(B,C):def test(self):B.test(self)#调用B

上面的逻辑变成了如图所示:




转载于:https://www.cnblogs.com/HDK2016/p/10964792.html

相关文章:

hive中array嵌套map以及行转列的使用

1. 数据源信息 {"student": {"name":"king","age":11,"sex":"M"},"sub_score":[{"subject":"语文","score":80},{"subject":"数学","score&qu…

SpringBoot 操作elasticsearch

SpringBoot 操作elasticsearch 版本环境 jdk1.8elasticsearch 7.6.1 maven <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>注意版本&#xf…

替换WCF默认序列化方式

创建类 : using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ServiceModel.Description; using System.Xml; using System.Runtime.Serialization; namespace Kingge.Mini.Network { public class NetDataContra…

Linux下vi编辑器命令精华版

最近开始使用vi编辑器&#xff0c;用了几天&#xff0c;发现其实还是比较好用的。对自己常用的命令做个总结&#xff0c;以备实时查阅。一下内容是对网络多篇文章的总结。进入vi的命令&#xff1a;vi filename :打开或新建文件&#xff0c;并将光标置于第一行首 vi filename &…

测试用例评审关注点

测试用例评审关注点 1、用例设计是否清晰、合理、简洁&#xff1b; 2、用例是否高效对需求进行覆盖&#xff0c;是否覆盖测试需求上的所有功能点&#xff1b; 3、优先级是否合理&#xff1b; 4、用例是否有很好的可执行性&#xff08;例如用例的“执行步骤”、“期待结果”是否…

命令行收集(DOS/Linux/nc/xscan/xsniffer)

#1 一&#xff1a; net use \\ip\ipc$ " " /user:" " 建立IPC空链接 net use \\ip\ipc$ "密码" /user:"用户名" 建立IPC非空链接 net use h: \\ip\c$ "密码" /user:"用户名" 直接登陆后映射对方C&#xff1a;到…

偏前端 - vue-cli(axios请求数据==》token+按接口参数顺序(参数值拼接base64)- MD5)...

token按接口参数顺序&#xff08;参数值拼接base64&#xff09;-> MD5) 请教于“喵咪”&#xff0c;再此特别鸣谢&#xff01;~ 特别强调&#xff1a;import qs from qs; 这个内部方法一定要用哦。参数签名base64md5都成功的情况华。接口还是爆500&#xff0c;就是和这个有关…

Docker 搭建elasticsearch 7.6.x集群

Docker 搭建elasticsearch 7.6.x集群 文章目录拉取镜像设置Elasticsearch挂载目录编写elasticsearch.yml配置文件node-1node-2node-3创建镜像验证是否搭建成功问题max virtual memory areas vm.max_map_count [65530] is too low, increase to at least参考拉取镜像 docker pu…

乐嘉性格色彩分析测试题

乐嘉<性格色彩>分析测试题 说明&#xff1a;最符合你的句子用红色作标记 1. 关于人生观&#xff0c;我的内心其实是&#xff1a; A 希望能够有尽量多的人生体验&#xff0c;所以会有非常多样化的想法。 B在小心合理的基础上&#xff0c;谨慎地确定自己的目标&#xff…

OAuth_1

OAuth2.0是一个应用之间彼此访问数据的开源授权协议。比如&#xff0c;一个游戏应用可以 访问Facebook的用户数据。用户访问web游戏应用&#xff0c;该游戏应用要求用户通过Facebook 登录。用户登录到Facebook&#xff0c;再重定向回游戏应用&#xff0c;游戏应用就可以访问用户…

ubuntu 使用阿里云 apt 源

以下内容来自 https://opsx.alibaba.com/mirror Ubuntu对应的“帮助”信息 修改方式&#xff1a;打开 /et/apt/sources.list将http://archive.ubuntu.com/替换为mirrors.aliyun.com即可 PS&#xff1a;网络上的信息&#xff0c;一定得注意时效性。以下内容&#xff0c;均为此时…

ecos 编译时无法找到 tclConfig.sh 和 tkConfig.sh

这是因为 tcl-devel tk-devel 一般系统中默认是不安装的&#xff0c;至少cent-os 5.5 和fedora 11是这样的&#xff0c;安装这两个包即可。 # yum install tcl-devel tk-devel 补记&#xff1a; ubuntu 10.04.2 上为了便于多个版本的tcl的存在&#xff0c;tcl被安装的位置不太一…

从消息处理角度看应用程序与windows的关系(图示)

转载于:https://blog.51cto.com/gzkhrh/338533

002:用Python设计第一个游戏

笔记 什么是BIF&#xff1f; 答&#xff1a;BIF 即 Built-in Functions&#xff0c;内置函数。为了方便快速编写脚本程序&#xff0c;Python 提供了非常丰富的内置函数&#xff0c;我们只需要直接调用即可&#xff0c;例如 print() 的功能是“打印到屏幕”&#xff0c;input() …

哑谜,回文和暴力之美

暴力搜索是一个有趣的东西。至少刘汝佳是这么认为的。编程之美的4.10节就是典型的暴力题。虽然作者将其难度定义为一颗星&#xff0c;但却不能因此认为这个类型的问题就是那么容易的&#xff0c;很多可能需要一些有创造力的想法。 不妨试试下面这几道题&#xff1a; Island of …

身份证敏感信息处理 图片添加蒙版

实现效果 需要的jar包 <!-- https://mvnrepository.com/artifact/com.jhlabs/filters --><dependency><groupId>com.jhlabs</groupId><artifactId>filters</artifactId><version>2.0.235-1</version></dependency> 调…

Linux bash管道符“|”使用介绍与例子

https://blog.csdn.net/wangqianyilynn/article/details/75576815转载于:https://www.cnblogs.com/dhName/p/10967718.html

PostgreSQL第一步:安装

PostgreSQL是一个自由的对象-关系数据库服务器&#xff08;数据库管理系统&#xff09;&#xff0c;它在灵活的BSD-风格许可证下发行。它在其他开放源代码数据库系统&#xff08;比如MySQL和Firebird&#xff09;&#xff0c;和专有系统比如Oracle、Sybase、IBM的DB2和Microsof…

【Henu ACM Round#15 A】 A and B and Chess

【链接】 我是链接,点我呀:) 【题意】 在这里输入题意 【题解】 统计大写和小写的个数。 比较答案。输出即可。 【代码】 #include <bits/stdc.h> using namespace std;string s[10]; map<char,int> dic; int inc[300];int main() {for (int i 0;i < 8;i)cin…

[转载] static class 静态类(Java)

一般情况下是不可以用static修饰类的。如果一定要用static修饰类的话&#xff0c;通常static修饰的是匿名内部类。   在一个类中创建另外一个类&#xff0c;叫做成员内部类。这个成员内部类可以静态的&#xff08;利用static关键字修饰&#xff09;&#xff0c;也可以是非静态…

tomcat监控-psi-probe使用

什么是psi-probe 这是一款 Tomcat 管理和监控工具&#xff0c;前身是 Lambda Probe。由于 Lambda Probe 2006不再更新&#xff0c;所以 PSI Probe 算是对其的一个 Fork 版本并一直更新至今。 下载 下载地址&#xff1a;https://github.com/psi-probe/psi-probe 百度网盘地址…

配置文件app.config

无论对于客户端程序还是web应用程序&#xff0c;配置文件的作用不言而喻&#xff0c;现总结用法如下&#xff1a; 1. 创建配置节类 必须创建继承自ConfigurationSection的对象才能进行配置数据读写操作&#xff0c;ConfigurationSection提供了索引器用来获取和设置配置数据&…

windows远程桌面如果超出最大连接数, 使用命令行mstsc /console登录即可

远程桌面如果超出最大连接数, 使用命令行mstsc /console登录即可。 &#xff08;也可以用 mstsc /admin&#xff09; 可以在运行里使用mstsc /console /v:IP:远程端口即可强制登录; 如果直接在远程桌面连接端使用就直接输入/console /v:IP:远程端口. 如&#xff1a;mstsc /cons…

AppiumForWin安装

尝试安装Windows版本的Appium参考&#xff1a;http://www.cnblogs.com/fnng/p/4540731.html第一步&#xff1a;安装nodehttps://nodejs.org/en/安装成功后使用&#xff1a;node -v&#xff0c;进行验证第二步&#xff1a;安装Appium下面的方法失败&#xff1a;原因下载不成功&a…

prometheus--初见

什么是prometheus Prometheus&#xff08;普罗米修斯&#xff09;是一个开源系统监控和警报工具&#xff0c;最初是在SoundCloud建立的。自2012年成立以来&#xff0c;许多公司和组织都采用了普罗米修斯&#xff0c;该项目拥有一个非常活跃的开发者和用户社区。它现在是一个独立…

JavaScript时间日期格式化

/** 时间对象的格式化;*/ Date.prototype.format function(format) {/** eg:format"YYYY-MM-dd hh:mm:ss";*/var o {"M" :this.getMonth() 1, // month"d" :this.getDate(), // day"h" :this.getHours(), // hour"m" :th…

Hello World

作为所有编程语言的起始阶段&#xff0c;HELLO WORLD占据着无法改变的地位&#xff0c;所有中/英/法/德/美……版本的编程教材中&#xff0c;HELLO WORLD总是作为第一个TEST记录于书本之中&#xff0c;所有的编程第一步就在于此了&#xff01;经典之中的经典&#xff01;HELLO …

POJ 1144 Network (求割点)

题意&#xff1a; 给定一幅无向图&#xff0c; 求出图的割点。 割点模板&#xff1a;http://www.cnblogs.com/Jadon97/p/8328750.html 分析&#xff1a; 输入有点麻烦&#xff0c; 用stringsteam 会比较简单 #include<cstdio> #include<iostream> #include<queu…

mongoose简单使用

介绍&安装 官网&#xff1a;http://www.mongoosejs.net/ npm i -S mongoose 使用 1.连接mongodb&创建模型 var mongoose require(mongoose)​//1、连接mongodb mongoose.connect(mongodb://localhost/test)​//2、设置文档结构var userSchema new mongoose.Schema…

Codeforces Round #563 (Div. 2)/CF1174

Codeforces Round #563 (Div. 2)/CF1174 CF1174A Ehab Fails to Be Thanos 其实就是要\(\sum\limits_{i1}^n a_i\)与\(\sum\limits_{n1}^{2n}a_i\)差值最大&#xff0c;排一下序就好了 CF1174B Ehab Is an Odd Person 一个显然的结论就是如果至少有一个奇数和一个偶数&#xff…