类
python中类(class)的元素组成:类属性和类中方法。
通常情况下,可以为类添加任意属性,但是为了限制class的属性的任意添加,需要引用一个特殊是类属性:__slots__,使用后,在某些情况下,可以节约大量内存空间。
class test(object):
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age=age
# 实例化并添加属性
x=test('aaa',12)
x.aa=6
# 报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'test' object has no attribute 'aa'
此处需要注意,在python2中,如果class不是继承了object的新式类的话,限制就是无效的,如果是python3,则对所有类的限制都是有效的。
class test():
__slots__ = ('name', 'age')
def __init__(self, name, age):
self.name = name
self.age=age
# 实例化并添加属性
x=test('aaa',12)
x.aa=6 # 不会报错
私有属性:两个下划线__开头的属性,不能在类的外部调用,只能在类中调用。
class test():
def __init__(self, name):
self.__name1=name
# 实例化
aa=test('xyz')
# 调用私有属性,报错
print(aa.__name1)
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: test instance has no attribute '__name1'
私有方法:两个下划线__开头的方法,不能在类的外部(实例化后直接调用会失败)调用,只能在类中调用。
class test():
def __init__(self, name):
self.__name1=name
def __echo(self):
print(self.__name1)
def echo(self):
self.__echo()
# 实例化
aa=test('xyz')
# 调用私有方法,报错
aa.__echo()
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
AttributeError: test instance has no attribute '__echo'
# 使用类中方法间接调用
aa.echo() # 输出 xyz
构造方法:
__init__,在类实例化时被调用,第一个参数必须为实例自身。
class test():
name1 = 'abc'
def __init__(self, name):
self.name1=name
print(self.name1)
print(test.name1) # 调用类属性
# 实例化
aa=test('xyz')
# 返回
xyz
abc
普通方法:
必须在类实例化之后才能调用,而且第一个参数必须为实例自身(通常写作self)。
class test():
def m(self, a):
print(a)
# 实例化之后,才能调用方法
t=test()
t.m('111111') # 结果 111111
静态方法:
以装饰器的形式,在函数之上添加 @staticmethod来实现,作用:赋予该函数方法能够无需类实例化而直接由类调用,所以无需实例化对应的参数 self。
class test():
@staticmethod
def m(a):
print(a)
# 直接调用方法
test.m('111111') # 结果 111111
比较特殊的一种装饰器 @property,可以将方法设置为实例的属性,结合另一个装饰器,可以实现同一个方法,能够对类属性(属性名为方法名)同时进行读写的操作,当只设置 @property时,属性为只读。
class test():
def __init__(self, name):
self._name=name
@property
def m(self):
return self._name
@m.setter
def m(self, name):
self._name=name
# 实例化之后,查看m属性值,为其属性m设置值
t=test(111111)
t.m # 结果 111111
t.m='22'
print(t.m)# 结果 22
类方法:
在函数之上添加 @classmethod来实现,方法所使用的首个参数为类自身,可以在类实例化之后调用,也可以直接由类调用。
class test():
name = 'abc'
@classmethod
def m(cls, name):
print(name)
print(cls.name)
print(test.name) # 与上一行等效
# 直接调用方法
test.m('111')
# 返回结果
111
abc
abc
魔法函数
函数形式__init__,也就是 由双下划线所包围。
常见魔法函数:
类实例化的时候所调用的第一个方法:
__new__
第一个参数是这个类自身(通常写作cls),其他的参数是用来传递给 __init__ 方法,它可以决定是否使用该\ __init__ 方法,即调用其他类的构造方法或者直接返回其他类的实例来作为本类的实例,如果 __new__ 没有返回实例对象,则 __init__ 不会被调用。
该方法的经典用法,以 单例模式为例说明。
class test(object):
def __new__(cls, name):
if not hasattr(cls, '_instance'):
cls._instance = object.__new__(cls)
return cls._instance
def __init__(self, name):
print(name)
# 实例化两个实例,并查看实例的id
>>> a=test('jim')
jim
>>> b=test('bob')
bob
>>> id(a)
50336936L
>>> id(b)
50336936L
两个实例的id相同,即在内存中指向同一个地址,单例模式使系统中一个类只有一个实例,实现了对实例个数的控制,节约了系统资源。
类实例化时的操作:
__init__
类实例化时,赋值技巧:
class Models():
def __init__(self, **kwargs):
self.__dict__ = kwargs
# 实例化
model = Models(hidden_size=100, num_layers=3, learning_rate=3e-4)
print(model.__dict__)
当参数列表 (List of Arguments) 很大的时候,该方法比较高效。
实例被销毁时的操作:
__del__
上下文管理,支持with关键字的方法:
__enter__
__exit__
也可以通过导入的方式(from contextlib import contextmanager),以装饰器(@contextmanager)的方式代替。
比较方法,举例依次为 <、=、>:
__lt__
__eq__
__gt__
通常创建包含比较的类时,需要将各种情况都要包含:<、<=、=、>=、>,但是可以通过装饰器的方式进行简化。
from functools import total_ordering
@total_ordering
class cmp_value():
def __init__(self, value):
self.v = value
def __lt__(self, other):
return self.v < other.v
def __eq__(self, other):
return self.v == other.v
print(cmp_value(12) > cmp_value(3)) # 返回 True
增量赋值运算方法,举例依次为 +=、-=、*=、%=:
__iadd__
__isub__
__imul__
__imod__
迭代方法:
__iter__
想让object变成可迭代对象,就用这个方法,之后可以在object上使用for循环。
定义被 repr() 调用时的行为:
__repr__
该方法必须返回一个可输出的object,如字符串。
定义被 print或者str() 调用时的行为:
__str__
定义被 format() 调用时的行为:
__format__
定义设置容器中指定元素的行为:
__setattr__
定义获取容器中指定元素的行为:
__getattr__