首页 > 编程语言 > 详细

python学习笔记16

时间:2020-04-02 19:38:57      阅读:59      评论:0      收藏:0      [点我收藏+]

python学习笔记16

多态

多态:一个类型表现出来多种状态。python中一个子类可以表现其本身的类型,同时它还具有其所有父类的类型。

super方法

先看一个实例:

class A:
    def func(self):print(‘A‘)
class B(A):
    def func(self):
        super().func()
        print(‘B‘)
class C(B):
    def func(self):
        super().func()
        print(‘C‘)
C().func()
"""
A
B
C
"""
# 可以看出super好像是寻找父类
# 其实只是在单继承的情形下super是找父类
# 而对于多继承的情况:
class A:
    def func(self):print(‘A‘)
class B(A):
    def func(self):
        super().func()
        print(‘B‘)
class C(A):
    def func(self):
        super().func()
        print(‘C‘)
class D(B,C):
    def func(self):
        super().func()
        print(‘D‘)
D().func()   
"""
A
C
B
D
"""
# 但其实super是按照MRO顺序来寻找当前类的上一个类
# 而MRO顺序是根据C3算法计算得出的

封装

广义上:把方法和属性封装起来,外部不能直接调用,只能通过类的名字调用。

狭义上:把方法和属性封装起来,外部不能调用,只能类内部使用。

class A(object):
    def __init__(self,username,passwd):
        self.username = username
        self.__pswd = passwd
    def get_pswd(self):
        return self.pswd
    def change_pswd(self):
        pass
# 在给对象的一个属性前加上了双下划线__后,称这个属性为私有的
# 所有私有的方法或者属性都不能在类的外部调用,只能在类的内部使用
# 但是可以在类的内部定义方法使得在外部能够查看私有属性(如get_私有属性名)
# 但是这个方法只能查看,不能修改!
# 当然如果想修改的话也可以定义一个修改函数,只能根据修改函数指定的方式改(change_私有属性名)

# 私有的静态变量如下:
class A:
    count = 1 # 非私有
    __num = 2 # 私有
    # 可以在内部定义方法查看私有静态变量
    def func(self):
        print(A.__num)
print(A.count) # 1
A().func() # 2
print(A.__num) # AttributeError: type object ‘A‘ has no attribute ‘__num‘

所有的私有化都是为了让用户不在外部调用类内部的某个名字(静态变量,方法,属性等)。

完成了私有化的类的封装度更高,相应的其各种属性和方法的安全度也更高,但是代码相对也变得更加复杂。

那么加了双下划线的名字为什么不能从类的外部调用了呢?

# 观察一个有私有静态变量的类
class A:
    num1 = 1
    __num2 = 2
    __num3 = 3
# 查看类的内容
print(A.__dict__) 
# {‘__module__‘: ‘__main__‘, ‘num1‘: 1, ‘_A__num2‘: 2, ‘_A__num3‘: 3, ‘__dict__‘: <attribute ‘__dict__‘ of ‘A‘ objects>, ‘__weakref__‘: <attribute ‘__weakref__‘ of ‘A‘ objects>, ‘__doc__‘: None}
# 可以看到私有静态变量变成了_A__num2和_A__num3
# 试着用这种名字进行调用
print(A()._A__num2) # 2
print(A()._A__num3) # 3
# 所以私有化并不是真正的无法调用,只是对象名字被另一种规则更改了

私有的内容能否被子类使用?

class A:
    def __init__(self):
        self.__func()
    def __func(self): # 这个函数实际是_A__func
        print(‘A‘)
class B(A):
    def __func(self): # 这个函数实际是_B__func
        print(‘B‘)
B() # A
# !!!上述代码实现过程:
# 在调用B()的时候,创建B类的实例,首先寻找__init__方法
# 由于B类自己没有这个方法,所以去父类(A类)寻找
# 在A的__init__方法中执行self.__func()
# 实际上是执行self._A__func(),而这个方法在B类中没有
# 所以去A类中寻找,执行的是print(‘A‘)!

所以,私有的内容不能被子类使用!!!

在其他语言中数据的级别都有哪些,在python中又有哪些

  • public:公有的,类内类外都能使用,父类子类都能使用。
  • protect:保护的,类内能用,父类子类都能使用,类外不能用
  • private:私有的,只有类内能用。

python支持public和private,不支持protect。

property装饰器

在类内部的方法定义前加上@property,将方法伪装成属性。(property装饰的方法不能有其他参数)

from math import pi
class circle:
    def __init__(self,r):
        self.r = r
    @property
    def area(self):
        return pi*self.r**2
a = circle(3)
print(a.r) # 3
print(a.area) # 28.274333882308138
# 这里将area方法伪装成了一个属性
# 调用的时候不需要使用实例化对象.area()

property装饰器的加入是为了使逻辑完善。就像上述代码中的例子,对于circle类来说,它的半径r是一个属性,而它的面积按照逻辑来说也应该是一个circle的属性而不应该是它的一个方法(一般而言,名词一般是一个属性,动词更像是一个方法)。所以说property一般可以去修饰一些容易变动(变动的值需要通过方法实现)的属性。

# property的其他使用
class User:
    # 定义用户名和密码
    def __init__(self,usr,pwd):
        self.usr = usr
        self.__pwd = pwd
    # 查看密码
    @property
    def pwd(self):
        return self.__pwd
    # 修改密码
    @pwd.setter
    def pwd(self,new_pwd):
        # 在这里修改可以设置要求
        if isinstance(new_pwd,str):
        	self.__pwd = new_pwd
user = User(‘aaa‘,‘123‘)
print(user.pwd) # 123
user.pwd = ‘456‘
print(user.pwd) # 456
# 尝试设置数字为密码
user.pwd = 789
print(user.pwd) # 456
# 密码修改失败
# property除了setter方法外还有一个deleter方法(不常用)可以删除属性
# 用法跟setter基本一样

反射

用字符串数据类型的名字来操作这个名字对应的函数\实例变量\绑定方法。

反射对象的实例变量,反射类的静态变量、绑定方法

class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def func(self):
        print(‘function‘)
Lieve = Person(‘Lieve‘,22)
Mark = Person(‘Mark‘,23)
# 调用属性
ret1 = getattr(Lieve,‘name‘) # 反射对象的实例变量
ret2 = getattr(Lieve,‘age‘)
print(ret1,‘,‘,ret2) # Lieve , 22
ret3 = getattr(Mark,‘name‘)
ret4 = getattr(Mark,‘age‘)
print(ret3,‘,‘,ret4) # Mark , 23
# 调用方法
f1 = getattr(Lieve,‘func‘) # 反射对象的绑定方法
f1() # function
# 将调用方式对象名.属性(方法)名==>getattr(对象名,‘属性(方法)名‘)
# 反射类的静态变量、绑定方法可同样实现
# 类名.属性(方法)名==>getattr(类名,‘属性(方法)名‘)

反射模块(包括被导入的模块,当前执行的py文件即脚本)中的所有变量

模块名.属性(方法)名==>getattr(模块名,‘属性(方法)名‘)

python学习笔记16

原文:https://www.cnblogs.com/20-03-14/p/12622388.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!