«

Python第十一课,类的权限

时间:2023-2-27 21:26     作者:wen     分类: Python


属性私有化
为了更好的保护属性安全, 即不能随意修改, 将属性定义为私有属性, 添加一个可调用的方法去访问.

语法 : 两个下划线开头, 声明该属性为私有, 不能再累的外部被使用或直接访问.

私有化方法
私有化方法和私有化属性概念一样, 有些重要的方法, 不允许外部调用, 防止子类意外重写, 把普通的方法设置成私有化方法.

特效: 私有化方法一般是类内部调用, 子类不能继承, 外部不能调用.

单下划线, 双下划线, 头尾双下划线说明:

xxx 前面加一个下划线, 以单下划线开头的表示的是protected类型的变量, 即保护类型智能允许其本身与子类进行访问, 不能使用 from xxx import * 的方式导入.
xxx_前后两个下划线, 魔术方法, 一般是Python自有, 开发者不要创建这类型的方法
xxx
后面单下划线, 避免属性名与Python关键字冲突

# 私有属性 私有化方法 property属性
class Person:
    __name: str = ''  # 定义一个私有化类属性

    def __init__(self):
        self.__age = 30  # 私有化属性
        pass

    def __eat(self):  # 私有化方法
        print('吃东西')
        pass

    # def get_age(self):  # 私有属性的访问
    #     return self.__age
    #     pass
    #
    # def set_age(self, age):  # 私有属性的设置
    #     if 0 < age < 150:  # 这个比其它语言更贴近生活
    #         self.__age = age
    #     else:
    #         print('年龄参数有误')
    #     pass

    def run(self):
        print('飞快的跑')

        pass
        # 定义一个类属性 实现通过直接访问属性的形式去访问私有的属性

    # age = property(get_age, set_age)

    # 通过装饰器得方法去声明
    @property  # 提供一个getter
    def age(self):
        return self.__age

    @age.setter  # 提供一个setter
    def age(self, age):
        if 0 < age < 150:  # 这个比其它语言更贴近生活
            self.__age = age
        else:
            print('年龄参数有误')
        pass

p = Person()
print(p.age)
p.age = 199
print(p.age)

new
创建并返回一个实例对象, 如果new只调用了一次, 就会得到一个对象. 继承自Object的新式类才有new这一魔术方法

new是在一个对象实例化的时候所调用的第一个方法
new至少必须要有一个参数
new必须返回实例对象
new不能调用自身的new方法, 即 return cls.new(cls), 否则报错,超过最大递归深度。

class Person:
    # 默认结构如下
    def __new__(cls, *args, **kwargs):
        print('new 方法调用')
        return super().__new__(cls, *args, **kwargs)
        pass
    def __init__(self):
        print('init 方法调用')
        self.name = 'zhangsan'
        print(self.name)
        pass
    pass

p = Person()

# 在新式类中 new 才是真正的实例化方式, 为类提供外壳制造出实例框架, 然后调用该框架内的构造方法 __init__ 进行丰满操作

单例模式
是一种常用的软件设计模式, 目的, 确保某一个类只有一个实例存在

# 参加一个单例对象
class Db:
    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'): # 如果不存在就开始创建
            cls._instance = super().__new__(cls, *args, **kwargs)
        return cls._instance
        pass

    pass

db1 = Db()
print(id(db1))
db2 = Db()
print(id(db2))

输出结果:

24307720
24307720

错误与异常处理

# 语法格式
try:
    '可能出现错误的代码块'
except: # 指定类型捕获异常
    '出错之后执行的代码块'
else:
    '没出错的代码块'
finally:
    '不管有没有出错都执行的代码块'

except 在捕获错误异常的时候, 是要根据具体的错误类型来捕获

# Exception 可以捕获所有的异常
try:
    li = [1, 2, 3, 4]
    # print(li[10])
    a = 10 / 0
    pass
except Exception as msg:
    # 捕获异常
    print(msg)
    pass

自定义异常

# 自定义异常
class MyException(Exception):
    def __init__(self, length):
        """
        初始化类
        :param len: 长度
        """
        self.length = length
        pass

    def __str__(self):
        return "你输入的长度是:%s, 已经超过规定长度" % str(self.length)

        pass

    pass

def name_test():
    name = input('请输入姓名:')
    if len(name) > 4:
        raise MyException(len(name))
    else:
        print(name)
        pass
    pass

try:
    name_test()
except MyException as msg:
    print(msg)
    pass

动态添加属性和方法

import types  # 添加方法的库

# 动态添加属性和方法
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

        pass

    def __str__(self):
        return '{}今年{}岁了'.format(self.name, self.age)

    pass

z3 = Person('zhangsan', 18)
print(z3)

z3.weight = 80  # 动态添加属性
print(z3.weight)

li4 = Person('lisi', 20)
print(li4)
li4.school = "北京大学"
print(li4.school)  # 动态添加属性

def func(self):
    print('{}的体重{}kg'.format(self.name, self.weight))
    pass

# 动态添加方法
z3.print_info = types.MethodType(func, z3)
z3.print_info()  # 调用动态方法

@classmethod
def classfun(cls):
    print('类方法')

@staticmethod
def staticfun():
    print('静态方法')

# 动态添加类方法
Person.class_method = classfun
Person.class_method()

# 动态添加静态方法
Person.static_method_ = staticfun
Person.static_method_()

slots属性
python 允许在定义class的时候, 定义一个特殊的slots变量, 来限制该class实例添加的属性.

只有在slots变量中的属性才能被添加, 没有在slots变量中的属性会添加失败. 可以防止其他人在调用类的时候胡乱添加属性和方法. slots属性子类不会继承, 只有在当前类中有效。

# __slots__ 属性
# 限制要添加的实例属性
# 节约内存空间
class Person:
    # __slots__ = ('name','age')
    def __str__(self):
        return '{}---{}'.format(self.name,self.age)
    pass

xw = Person()
xw.name = '小王'
xw.age = 20
# xw.sex = '男'  # 不能添加
print(xw)

print(xw.__dict__)  # 所有的属性都在这里存储
# 可以看到 定义了 slots 属性后, 实例不能随意创建不在slots实例属性, 同时实例当中也不再有__dict__属性了

# 在继承关系中使用 __slots__
# 子类未声明 __slots__时, 子类可以随意的添加实例属性
# 子类声明 __slots__ 时, 子类会继承父类 + 自己定义的(子类和父类的交集)
class SubPerson(Person):
    __slots__ = ()
    pass

ln = SubPerson()

ln.name = '男'
print(ln.name)

标签: python基础