zoukankan      html  css  js  c++  java
  • 深入类

    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.name
    12 
    13 use_class=MyClass('xiaoqiang')
    14 print('调用类的属性:',use_class.i)
    15 print('调用类的方法:',use_class.f())
    #程序执行结果如下:
    1 ================= RESTART: C:/Users/DL He/Desktop/类的构造方法.py =================
    2 调用类的属性: 123
    3 调用类的方法: 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 <module>
    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:Pythonworkspacedatatime20171121>python __init__()方法_1.py
    2 我是不带参数的__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:Pythonworkspacedatatime20171121>python __init__()方法_1.py
    2 我是带一个参数的__init__方法,参数值为: hello
    3 类实例化结束
    #由执行结果看到,调用的是带了一个param参数的构造方法,若把类的实例化语句更改为:
    1 DefaultIinit()
    #执行结果为:
    1 D:Pythonworkspacedatatime20171121>python __init__()方法_1.py
    2 Traceback (most recent call last):
    3   File "__init__()方法_1.py", line 12, in <module>
    4     DefaultInit()
    5 TypeError: __init__() missing 1 required positional argument: 'param'
    #或更改为:
    1 DefaultInit('hello','world')
    #执行结果为:
    1 D:Pythonworkspacedatatime20171121>python __init__()方法_1.py
    2 Traceback (most recent call last):
    3   File "__init__()方法_1.py", line 12, in <module>
    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:Pythonworkspacedatatime20171121>python __init__()方法_1.py
    2 我是不带参数的__init__方法。
    3 类实例化结束
    #由执行结果看到,调用的构造方法除了self外,没有其他参数。若把类的实例化语句更改为如下:
    1 DefaultInit('hello')
    #执行结果如下:
    1 D:Pythonworkspacedatatime20171121>python __init__()方法_1.py
    2 Traceback (most recent call last):
    3   File "__init__()方法_1.py", line 13, in <module>
    4     DefaultInit('hello')
    5 TypeError: __init__() takes 1 positional argument but 2 were given
    #或更改为:
    1 DefaultInit('hello','world')
    #执行结果如下:
    1 D:Pythonworkspacedatatime20171121>python __init__()方法_1.py
    2 Traceback (most recent call last):
    3   File "__init__()方法_1.py", line 13, in <module>
    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=0
    17 print('修改后分数:',stu.score)
    18 stu.info()
    #程序执行结果如下:
    1 D:Pythonworkspace>python 类的访问权限.py
    2 修改前分数: 96
    3 学生:xiaoming;分数:96
    4 修改后分数: 0
    5 学生: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=0
    17 print('修改后分数:',stu.__score)
    18 stu.info()
    #程序执行结果如下:
    1 D:Pythonworkspace>python 类的访问权限.py
    2 Traceback (most recent call last):
    3   File "类的访问权限.py", line 14, in <module>
    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.__score
    15 
    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 类的访问权限.py
    2 修改前分数: 96
    3 学生:xiaoming;分数:96
    4 修改后分数: 96
    5 学生: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.__score
    15 
    16     def set_score(self,score):
    17         self.__score=score
    18 
    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 类的访问权限.py
    2 修改前分数: 96
    3 学生:xiaoming;分数:96
    4 修改后分数: 0
    5 学生: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.__score
    15 
    16     def set_score(self,score):
    17         self.__score=score
    18 
    19     if 0<=score<=100:
    20         self.__score=score
    21     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 修改前分数:96
    2 学生:xiaoming;分数:96
    3 请输入0到100的数字。
    4 修改后分数:96
    5 学生: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 <module>
    10     pri_pub.__foo()
    11 AttributeError: 'PrivatePublicMethod' object has no attribute '__foo'
    #由输出结果看到,私有方法和私有变量类似,不能通过外部调用。
     
     
  • 相关阅读:
    Goldbach's Conjecture
    查找素数
    最大公约数和最小公倍数
    迭代求立方根
    计算两个矩阵的乘积
    随机选择算法
    有几个PAT
    python3学习笔记之安装
    Ubuntu 16.04卸载一些不必要的预装软件
    Xshell连接不上虚拟机提示ssh服务器拒绝了密码,请再试一次
  • 原文地址:https://www.cnblogs.com/DLHe/p/7919404.html
Copyright © 2011-2022 走看看