"""
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
Python面向对象编程学习笔记3
最新推荐文章于 2024-09-01 16:57:39 发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)