初始化
定义了__init__
后就要传入其定义的所有参数。__init__
中所定义的属性直接与实例想联。
1 | class Student(object): |
访问限制
- 以双划线
__
开头,__
结尾的变量是特殊变量,特殊变量可以直接访问。 - 以一个下划线
_
开头的变量是保护变量,只允许其自身和子类使用,不能用form xx import *
。 - 以两个下划线
__
开头的变量是private变量,虽然可以访问,但是按照惯例,应该视为私有变量,只允许这个类访问,不应该访问。 - 如果要访问和更改内部私有变量,可以在类中设置相应的
set_item
,change_item
,get_item
方法来获得。
1 | class Student(object): |
实例属性和类属性
- 实例属性属于各个实例所有,互不干扰;
- 类属性属于类所有,所有实例共享一个属性;
- 不要对实例属性和类属性使用相同的名字,否则将产生难以发现的错误!实例属性的值会覆盖类属性的值
1 | # 添加类属性 |
继承和多态
- 继承就是说,我创建一个新的类别的时候,object处填写已有的一个类别,新类别是子类别,旧类别是父类别。
- 子类别会继承旧类别的所有的属性和方法;
- 子类别可以更改父类别的方法(会覆盖父类别的方法);
- 子类别可以添加新的方法
1 | class Animal(object): |
装饰器
简单来说,装饰器就是把另外一个函数当成参数传入到当前函数中并返回一个函数,这个函数会取代被装饰的函数。
装饰器的运行过程
先将被修饰函数放入修饰器中的函数,然后正常运行修饰器函数,当调用被修饰函数时,执行被修饰函数。如果需要传入的被修饰函数需要传参,那么在调用的函数中也要设置参数位置。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21# It’s not black magic, you just have to let the wrapper
# pass the argument:
def a_decorator_passing_arguments(function_to_decorate):
def a_wrapper_accepting_arguments(arg1, arg2):
print("I got args! Look: {0}, {1}".format(arg1, arg2))
function_to_decorate(arg1, arg2)
return a_wrapper_accepting_arguments
# Since when you are calling the function returned by the decorator, you are
# calling the wrapper, passing arguments to the wrapper will let it pass them to
# the decorated function
def print_full_name(first_name, last_name):
print("My name is {0} {1}".format(first_name, last_name))
print_full_name("Peter", "Venkman")
# outputs:
#I got args! Look: Peter Venkman
#My name is Peter Venkman
如果是在类中使用呢?方法和函数的唯一区别只在于第一个参数是self
。因此,我们只需要更改一下这个地方即可。
1 | def method_friendly_decorator(method_to_decorate): |
装饰器函数可以不带参数,也可以带参数。当装饰器函数带参数时,其实充当的是装饰器函数的构造器的功能,其携带的参数都可访问,但是不能被传入到「真正」的装饰器函数中,否则会起冲突!在定义装饰器时传入参数,我们可以更好地控制装饰器的行为。但是在构建简单的装饰器时,使用不带参数的即可。
1 | def methord_with_args(arg1): |
常见的内置装饰器函数
类方法@classmethod
在类中定义方法时使用@classmethod
装饰器可以不创建实例就被使用。被类方法装饰器装饰的函数虽然不用传入self
参数,但是仍需要传入一个cls
参数来表示其自身。这个cls
和self
一样是不能传变量的。
静态方法@staticmethod
静态方法可以不创建实例来调用类中的一个方法。静态方法不需要传入参数,但也可以传入参数。
1 | class Myclass: |
@property
用途1:与私有变量配合使用,来定义只读属性。
1 | class Person(): |
用途2:对类中的属性进行检查
原来,我们要对类中属性的设置进行检查,会这样写:1
2
3
4
5
6
7
8
9
10
11class Student(object):
def get_score(self):
return self._score
def set_score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
然后调用的时候会这样:1
2
3
4
5
6
7
8 s = Student()
60) # ok! s.set_score(
s.get_score()
60
9999) s.set_score(
Traceback (most recent call last):
...
ValueError: score must between 0 ~ 100!
但这样用两个方法太麻烦了,有了@property
这个装饰器,就会方便很多。我们把一个getter
方法变成属性,只需要加上@property
就可以了,此时,@property
本身又创建了另一个装饰器@score.setter
,负责把一个setter
方法变成属性赋值,于是,我们就拥有一个可控的属性操作:
1 | class Student(object): |
参考资料: