博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
深入类
阅读量:5776 次
发布时间:2019-06-18

本文共 10055 字,大约阅读时间需要 33 分钟。

1、类的构造方法
#在介绍之前,我们对前面的示例做一些改动,代码如下:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #类的构造方法 4  5 class MyClass(object): 6     i=123 7     def __init__(self,name):    #注意!这里是个坑:“__init__”的“__”符号是左右两个! 8         self.name=name 9 10     def f(self):11         return  'hello,'+self.name12 13 use_class=MyClass('xiaoqiang')14 print('调用类的属性:',use_class.i)15 print('调用类的方法:',use_class.f())
#程序执行结果如下:
1 ================= RESTART: C:/Users/DL He/Desktop/类的构造方法.py =================2 调用类的属性: 1233 调用类的方法: hello,xiaoqiang
#若类的实例化语句写法和之前一样,即:
1 use_class=MyClass()
#程序执行结果如下:
1 ================= RESTART: C:/Users/DL He/Desktop/类的构造方法.py =================2 Traceback (most recent call last):3   File "C:/Users/DL He/Desktop/类的构造方法.py", line 13, in 
4 use_class=MyClass()5 TypeError: __init__() missing 1 required positional argument: 'name'
#从代码和输出结果看到,实例化MyClass类时调用了__init__()方法。我们在代码中并没有指定调用__init__()方法,怎么会报__init__()方法错误呢?
#在Python中,__init__()方法是一个特殊方法,在对象实例化时会被调用。__init__()的意思时初始化,是initialization的简写。这个方法的书写方式是:先输入两个下划线,后面接着init,再接着两个下划线。这个方法也叫构造方法。在定义类时,若不显式地定义一个__init__()方法,则程序默认调用一个无参的__init__()方法。比如以下两段代码的使用效果是一样的:
#代码一:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8 -*- 3 #__init__方法 4  5 class DefaultInit(object): 6     def __init__(self): 7         print('类实例化时执行我,我是__init__方法。') 8  9     def show(self):10         print('我是类中定义的方法,需要通过实例化对象调用。')11 12 test=DefaultInit()13 print('类实例化结束。')14 test.show()
#程序执行结果如下:
1 ================ RESTART: C:/Users/L/Desktop/__init__()方法.py ================2 类实例化时执行我,我是__init__方法。3 类实例化结束。4 我是类中定义的方法,需要通过实例化对象调用。
#代码二:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8 -*- 3 #__init__方法_1 4  5 class DefaultInit(object): 6     def show(self): 7         print('我是类中定义的方法,需要通过实例化对象调用。') 8  9 test=DefaultInit()10 print('类实例化结束。')11 test.show()
#程序执行结果如下:
1 ================ RESTART: C:/Users/L/Desktop/__init__()方法.py ================2 类实例化结束。3 我是类中定义的方法,需要通过实例化对象调用。
#由上面的两段代码的输出结果看到,当代码中定义了__init__()方法时,实例化类时会调用该方法;若没有定义__init__()方法,实例化类时也不会报错,此时调用默认的__init__()方法。
#在Python中定义类时若没有定义构造方法(__initI__()方法),则在类的实例化时系统调用默认的构造方法。另外,__init__()方法可以有参数,参数通过__init__()传递到类的实例化操作上。
#既然__init__()方法是Python中的构造方法,那么是否可以在类中定义多个构造方法呢?我们来看下面3段代码:
#代码一:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8 -*- 3 #__init__()方法_1 4  5 class DefaultInit(object): 6     def __init__(self): 7         print('我是不带参数的__init__方法。') 8  9 DefaultInit()10 print('类实例化结束')
#程序执行结果如下:
1 D:\Python\workspace\datatime\20171121>python __init__()方法_1.py2 我是不带参数的__init__方法。3 类实例化结束
#在只有一个__init__()方法时,实例化没有什么顾虑。
#代码二:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8 -*- 3 #__init__()方法_1 4  5 class DefaultInit(object): 6     def __init__(self): 7         print('我是不带参数的__init__方法。') 8  9     def __init__(self,param):10         print('我是带一个参数的__init__方法,参数值为:',param)11 12 DefaultInit('hello')13 print('类实例化结束')
#程序执行结果如下:
1 D:\Python\workspace\datatime\20171121>python __init__()方法_1.py2 我是带一个参数的__init__方法,参数值为: hello3 类实例化结束
#由执行结果看到,调用的是带了一个param参数的构造方法,若把类的实例化语句更改为:
1 DefaultIinit()
#执行结果为:
1 D:\Python\workspace\datatime\20171121>python __init__()方法_1.py2 Traceback (most recent call last):3   File "__init__()方法_1.py", line 12, in 
4 DefaultInit()5 TypeError: __init__() missing 1 required positional argument: 'param'
#或更改为:
1 DefaultInit('hello','world')
#执行结果为:
1 D:\Python\workspace\datatime\20171121>python __init__()方法_1.py2 Traceback (most recent call last):3   File "__init__()方法_1.py", line 12, in 
4 DefaultInit('hello','world')5 TypeError: __init__() takes 2 positional arguments but 3 were given
#由执行结果看到,实例化类时只能调用带两个占位参数的构造方法,调用其它构造方法都会报错。
#代码三:
1 class DefaultInit(object):2     def __init__(self,param):3         print('我是带一个参数的__init__方法,参数值为:',param)4 5     def __init(self):6         print('我是不带参数的__init__方法。')7 8 DefaultInit()9 print('类实例化结束')
#程序执行结果如下:
1 D:\Python\workspace\datatime\20171121>python __init__()方法_1.py2 我是不带参数的__init__方法。3 类实例化结束
#由执行结果看到,调用的构造方法除了self外,没有其他参数。若把类的实例化语句更改为如下:
1 DefaultInit('hello')
#执行结果如下:
1 D:\Python\workspace\datatime\20171121>python __init__()方法_1.py2 Traceback (most recent call last):3   File "__init__()方法_1.py", line 13, in 
4 DefaultInit('hello')5 TypeError: __init__() takes 1 positional argument but 2 were given
#或更改为:
1 DefaultInit('hello','world')
#执行结果如下:
1 D:\Python\workspace\datatime\20171121>python __init__()方法_1.py2 Traceback (most recent call last):3   File "__init__()方法_1.py", line 13, in 
4 DefaultInit('hello','world')5 TypeError: __init__() takes 1 positional argument but 3 were given
#由执行结果看到,实例化类时只能调用带一个占位参数的构造方法,调用其他构造方法都会报错。
#由以上几个实例我们得知,一个类中可定义多个构造方法,但实例化类时只实例化最后的构造方法,即后面的构造方法会覆盖前面的构造方法,并且需要根据最后一个构造方法的形式进行实例化。所以建议一个类中只定义一个构造函数。
 
2、类的访问权限
#在类内部有属性和方法,外部代码可以通过直接调用实例变量的方法操作数据,这样就隐藏了内部的复杂逻辑,例如:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #类的访问权限 4  5 class Student(object): 6     def __init__(self,name,score): 7         self.name=name 8         self.score=score 9 10     def info(self):11         print('学生:%s;分数:%s'%(self.name,self.score))12 13 stu=Student('xiaoming',96)14 print('修改前分数:',stu.score)15 stu.info()16 stu.score=017 print('修改后分数:',stu.score)18 stu.info()
#程序执行结果如下:
1 D:\Pythonworkspace>python 类的访问权限.py2 修改前分数: 963 学生:xiaoming;分数:964 修改后分数: 05 学生:xiaoming;分数:0
#由代码和输出结果看到,在类中定义的非构造方法可以调用类中构造方法实例变量的属性,调用的方式为self.实例变量属性名,如代码中的self.name和self.score。可以在类的外部修改类的内部属性。如果要让内部属性不被外部访问,该如何操作?
#要让内部属性不被外部访问,可以在属性名称前加两个下划线__。在Python中,实例的变量名如果以__开头,就会变成私有变量(private),只有内部可以访问,外部不能访问。据此,我们可以把student类改一改:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #类的访问权限 4  5 class Student(object): 6     def __init__(self,name,score): 7         self.__name=name 8         self.__score=score 9 10     def info(self):11         print('学生:%s;分数:%s'%(self.__name,self.__score))12 13 stu=Student('xiaoming',96)14 print('修改前分数:',stu.__score)15 stu.info()16 stu.__score=017 print('修改后分数:',stu.__score)18 stu.info()
#程序执行结果如下:
1 D:\Pythonworkspace>python 类的访问权限.py2 Traceback (most recent call last):3   File "类的访问权限.py", line 14, in 
4 print('修改前分数:',stu.__score)5 AttributeError: 'Student' object has no attribute '__score'
#由执行结果看到,我们已经无法从外部访问实例变量的属性__score了。
#这样可以确保外部代码不能随意修改对象内部的状态,通过访问限制的保护,代码更加安全。比如上面的分数对象是一个比较重要的内部对象,如果外部可以随便更改这个值,大家都随便更改自己成绩单中的分数,是比较危险的。
#如果外部代码要获取类中的name和score要如何操作呢?
#在Python中,可以为类增加get_attrs方法,获取类中的私有变量,例如上面的示例中添加get_score(name的使用方式类同)方法,代码如下:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #类的访问权限 4  5 class Student(object): 6     def __init__(self,name,score): 7         self.__name=name 8         self.__score=score 9 10     def info(self):11         print('学生:%s;分数:%s'%(self.__name,self.__score))12 13     def get_score(self):14         return self.__score15 16 stu=Student('xiaoming',96)17 print('修改前分数:',stu.get_score())18 stu.info()19 print('修改后分数:',stu.get_score())20 stu.info()
#由执行结果如下:
1 D:\Pythonworkspace>python 类的访问权限.py2 修改前分数: 963 学生:xiaoming;分数:964 修改后分数: 965 学生:xiaoming;分数:96
#由执行结果看到,通过get_score方法已经可以正确得到类内部的属性值。
#是否可以通过外部更改内部私有变量的值?
#在Python中,可以为类增加set_attrs方法,修改类中的私有变量,如更改上面示例中的score属性值,可以添加set_score(name使用方式类同)方法,代码如下:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #类的访问权限 4  5 class Student(object): 6     def __init__(self,name,score): 7         self.__name=name 8         self.__score=score 9 10     def info(self):11         print('学生:%s;分数:%s'%(self.__name,self.__score))12 13     def get_score(self):14         return self.__score15 16     def set_score(self,score):17         self.__score=score18 19 stu=Student('xiaoming',96)20 print('修改前分数:',stu.get_score())21 stu.info()22 stu.set_score(0)23 print('修改后分数:',stu.get_score())24 stu.info()
#程序执行结果如下:
1 D:\Pythonworkspace>python 类的访问权限.py2 修改前分数: 963 学生:xiaoming;分数:964 修改后分数: 05 学生:xiaoming;分数:0
#由程序执行结果看到,通过set_score方法正确更改了变量score的值。这里有个疑问,原先stu.score=0这种方式也可以修改score变量,为什么又要那么费劲定义私有变量,set.score的意义在于哪里呢?
#在Python中,通过定义私有变量和对应的set方法可以帮助我们做参数检查,避免传入无效的参数,如对上面的示例更改如下:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #类的访问权限 4  5 class Student(object): 6     def __init__(self,name,score): 7         self.__name=name 8         self.__score=score 9 10     def info(self):11         print('学生:%s;分数:%s'%(self.__name,self.__score))12 13     def get_score(self):14         return self.__score15 16     def set_score(self,score):17         self.__score=score18 19     if 0<=score<=100:20         self.__score=score21     else:22         print('请输入0到100的数字。')23 24 25 stu=Student('xiaming',96)26 print('修改前分数:',stu.get_score())27 stu.info()28 stu.set_score(-10)29 print('修改后分数:',stu.get_score())30 stu.info()
#程序执行结果如下:
1 修改前分数:962 学生:xiaoming;分数:963 请输入0到100的数字。4 修改后分数:965 学生:xiaoming;分数:96
#由输出结果看到,调用set_score方法时,如果传入的参数不满足条件,就按照不满足条件的程序逻辑执行。
#既然类有私有变量,那么有没有私有方法呢?
#是的,类也有私有方法。类的私有方法也是以两个下划线开头,声明该方法为私有方法,且不能在类外使用。私有方法的调用方式如下:
self.__private_methods
#我们通过下面的示例,进一步了解私有方法的使用:
1 #! /usr/bin/python3 2 #-*-coding:UTF-8-*- 3 #类的私有方法 4  5 class PrivatePublicMethod(object): 6     def __init__(self): 7         pass 8  9     def __foo(self):           #(私有方法)10         print('这是私有方法。')11 12     def foo(self):13         print('这是公共方法。')14         print('这是公共方法中调用私有方法。')15         self.__foo()16         print('公共方法调用私有方法结束。')17 18 pri_pub=PrivatePublicMethod()19 print('开始调用公共方法:')20 pri_pub.foo()21 print('开始调用私有方法:')22 pri_pub.__foo()
#程序执行结果如下:
1 D:\Pythonworkspace>python 类的私有方法.py 2 开始调用公共方法: 3 这是公共方法。 4 这是公共方法中调用私有方法。 5 这是私有方法。 6 公共方法调用私有方法结束。 7 开始调用私有方法: 8 Traceback (most recent call last): 9   File "类的私有方法.py", line 22, in 
10 pri_pub.__foo()11 AttributeError: 'PrivatePublicMethod' object has no attribute '__foo'
#由输出结果看到,私有方法和私有变量类似,不能通过外部调用。

 

 
 

转载于:https://www.cnblogs.com/DLHe/p/7919404.html

你可能感兴趣的文章
脱离“体验”和“安全”谈盈利的游戏运营 都是耍流氓
查看>>
慎用!BLEU评价NLP文本输出质量存在严重问题
查看>>
基于干净语言和好奇心的敏捷指导
查看>>
Node.js 2017企业用户调查结果发布
查看>>
“软”苹果水逆的一周:杂志服务崩溃,新机型遭泄露,芯片首架离职
查看>>
JAVA的优势就是劣势啊!
查看>>
ELK实战之logstash部署及基本语法
查看>>
帧中继环境下ospf的使用(点到点模式)
查看>>
BeanShell变量和方法的作用域
查看>>
LINUX下防恶意扫描软件PortSentry
查看>>
由数据库对sql的执行说JDBC的Statement和PreparedStatement
查看>>
springmvc+swagger2
查看>>
软件评测-信息安全-应用安全-资源控制-用户登录限制(上)
查看>>
我的友情链接
查看>>
Java Web Application 自架构 一 注解化配置
查看>>
如何 debug Proxy.pac文件
查看>>
Python 学习笔记 - 面向对象(特殊成员)
查看>>
Kubernetes 1.11 手动安装并启用ipvs
查看>>
Puppet 配置管理工具安装
查看>>
Bug多,也别乱来,别被Bug主导了开发
查看>>