Python面向对象编程学习笔记3

文章介绍了Python新式类的高级特性,包括新式类与经典类的区别,如何使用__slots__节省内存,描述符的概念及其在属性管理中的作用,__getattribute__方法的使用,以及装饰器在属性和方法上的应用。此外,还讨论了类方法、静态方法的使用以及通过__slots__优化大量对象内存占用的方法。
摘要由CSDN通过智能技术生成
"""
7.5 新式类的高级特性
7.5.1 什么是新式类
python 2.2之后版本的类都被称为新式类,2.2之前的叫做经典类,经典类兼容到2.7
新式类和经典类的区别是:新式类继承父类object,而经典类什么都不继承。所以新式类从创建之初就已经
"""
class OldStyleClass:
    pass
class NewStyleClass(object):
    pass
# 7.5.3 __slots__类属性
'''
在新式类中,每个实例对象都继承了父类object的__dict__属性,它使用这个字典来存储这个实例对象内所有可写属性
__slots__是一个序列类型的对象,它可以是列表、元组,或者是其他可迭代对象。在新式类中定义了__slots__时,原来
继承父类object的属性__dict__就不复存在。取而代之的是__slots__,他会节省内存,同时也更加安全。
'''
class ClassName(object):
    __slots__ = ['a']
class_ = ClassName()
class_.a = "100"
print(class_.a)
# class_.b = "200" AttributeError: 'ClassName' object has no attribute 'b'
print("----------")

# 描述类的变化
"""
python 2.2 引进了python描述符,这是一种创建托管属性的方法。描述符具有很多优点:
比如,保护属性不受修改、属性类型检查和自动更新某个依赖属性的值等。
简单的来说,一个类如果重写了__get__()、__set__()、__del__()这3种方法中至少一种方法及以上,
并且这个类的实例对象通常是另一个类的属性,那么这个类就是一个描述符。其中,__get__()用于访问属性,
__set__()用于设置属性值,__del__()则用于删除操作。
python是一种动态解释性语言,必须通过添加额外的数据类型检查代码才可以防止引用类型错误。
为了实现数据类型检查,下面中先定义一个描述符 TheString
"""
class TheString(object):
    def __init__(self):
        self.__name = "Default String"
    def __get__(self, instance, owner):
        return self.__name
    def __set__(self, instance, value):
        if type(value) is str:
            self.__name = value
        else:
            raise TypeError(str(value)) + "isn't a string"
class ClassName:
    value = TheString()
class_ = ClassName()
print("class_.value = " +class_.value)
print("----------")

# 7.5.4 特殊方法__getattribute__()
"""
如果找不到某个实例对象的属性,就会报AttributeError报错。为了避免报错,可以通过自定义__getattr__()方法
防止程序在找不到未定义实例对象的属性时抛出异常报错,中断程序。但不科学,也不推荐使用。
"""
class ClassName:
    value = "100"
    def __getattr__(self, item):
        return "default attr"
class_ = ClassName()
print("class_.value = " + class_.value)
print("class_.vvvvv = " + class_.vvvvv)
print("----------")
'''
__getatrr__()、__getatrribute__()都是访问属性的方法,但作用不太相同。
当访问某个实例对象的时候,__getattribute__()方法就会被无条件的被调用,如果
class 中定义了__getattr__(),则__get__()不会被调用(除非显示调用或引发AttributeError异常)
__getattribute__()在搜索属性时,先搜索类属性和数据描述符,如果搜索不到,则搜索实例属性和
非数据描述符,最后会找到默认的__getattr__()方法,返回一个值或者AttributeError异常。
'''
# 7.5.5 装饰器的区别
'''
下面的例子中,对ClassName.value()方法使用装饰器,当执行实例对象value时,会自动执行装饰器修饰的
ClassName.value()方法,并获取相应的返回值。简而言之,装饰器让实例对象的方法看上去像一个属性
'''
class ClassName:
    @property
    def value(self):
        return "100"
class_ = ClassName()
print("class_.value = "+class_.value)
print("----------")
'''
新式类有3种修饰器:@property、@property.setter和@property.deleter 分别用于定义一个属性的访问、修改、删除。
在下面的例子中,通过装饰器修饰了对value属性的访问、修改和删除。访问时得到的值是v的2倍,而修改时把值600除以2并赋值给v
删除的时候则会在控制台打印删除信息。
装饰器是闭包的一种应用。
'''
class ClassName:
    def __init__(self):
        self.v = 300.0
    @property
    def value(self):
        print("value.getter self.v =" + str(self.v))
        return self.v * 2
    @value.setter
    def value(self, value):
        print("value.setter self.v =" + str(value / 2))
        self.v = value / 2
    @value.deleter
    def value(self):
        print("value.deleter self.v")
        del self.v
class_ = ClassName()
print("class_.value = " + str(class_.value))
class_.value = 600
del class_.value
print("----------")

# 7.6 类的设计技巧
'''
7.6.1 调用父类方法 派生类重写了父类的方法时,可以通过使用super()方法调用父类方法.
'''
class BaseClassName:
    def print(self):
        print("BaseClassPrint")
class DerivedClassName(BaseClassName):
    def print(self):
        super(DerivedClassName, self).print()
        super().print()
        print("DerivedClassPrint")
derived = DerivedClassName()
derived.print()
print("----------")

'''
7.6.2 静态方法和类方法的区别
实例对象的方法只能被实例对象调用,而由@staticmethod修饰的静态方法和由@classmethod修饰的类方法都可以被类或实例对象调用。
通常来讲,静态方法一般通过类名调用,不用加参数self;而类方法的第一个参数要传类名进去。下例是由@staticmethod修饰的静态方法实例。
'''
class ClassName:
    def __init__(self):
        self.data = "100"
    @staticmethod
    def print_data(object_, name):
        print(str(name)+":"+object_.data)
    @classmethod
    def class_method(cls, data):
        class_ = ClassName()
        class_.data = data
        return class_
a = ClassName()
ClassName.print_data(a, "a")
print("----------")

'''
而由classmethod修饰的类方法十分有意思。从某种意义上讲,它体现了python的灵活性,可以最大限度地避免重构类带来地麻烦。
有了类方法之后,重构类不需要修改构造函数了,只需要把额外需要地部分添加到由@classmethod修饰的类方法中,然后像下面的
例子一样调用就可以了。
'''
class ClassName:
    def __init__(self):
        self.data = "100"
    def print_data(object_, name):
        print(str(name)+":"+object_.data)
    @classmethod
    def class_method(cls, data):
        class_ = ClassName()
        class_.data = data
        return class_
b = ClassName.class_method("200")
ClassName.print_data(b,"b")
print("----------")

# 创建大量对象时减少内存占用
'''
程序需要创建许多的对象,而内存又有限,此时不如把类当作简单的数据结构,使用新式类的__slots__特性
对于当成简单的数据结构的类而言,可以通过给类添加__slots__属性来极大地减少实例所占地内存,如下所示:
'''
class date:
    __slots__ = ['year', 'month', 'day']
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = year
        









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XF鸭

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值