Python Class 知识总结
一、 python类中的访问限制(常用)
1、属性的访问限制,Python 私有属性
Python 类中如果有属性不希望被外部访问,我们可以在属性命名时以双下划线开头( __ ),那么该属性就不能使用原变量名访问,使得该属性变为本类私有的(伪私有)。
但,如果一个属性以”xxx“的形式定义,那么它可以被外部访问。以”xxx“定义的属性在 Python 的类中是特殊属性,有很多预定义的特殊属性都是以“xxx”定义,所以我们不要把普通属性用”xxx“ 定义。
以单下划线开头的属性”_xxx”,虽然也可以被外部访问,但,按照习惯,他们不应该被外部访问,遵照编码规范我们也不该在外部访问 _xx 或 __xx 属性。
补充说明:加双下划线__xx 的属性,可以通过“ _类名__xx ”可以访问到属性的值。
如下圆类Circle的示例,我们将pi属性开头加上双下划线变成私有属性:
class Circle(object):
__pi = 3.14
def __init__(self, r):
self.r = r
def area(self):
"""
圆的面积
"""
return self.r **2* self.__pi
circle1 = Circle(1)
print(Circle.__pi) # 抛出AttributeError异常
print(circle1.__pi) # 抛出AttributeError异常
通过 Circle.__pi 与 circle1.__pi 访问 __pi 时 都会出现 AttributeError 异常,证明访问权限已被控制。
那么是不是我们就不能访问 __pi 变量?
不是,其实还是可以访问 __pi ,可以通过 Circle._Circle__pi 访问到 __pi 属性,为什么能这么访问这里不多讲,他与python的机制有关。
按照编码规范,他们不应该使用Circle._Circle__pi 访问到__pi属性。
2、方法的访问限制,Python私有访问
同属性的访问限制,方法的访问限制也是在方法名前加双下划线 ( __ ),它也是一种伪私有。
二、 Python类中的@classmethod、@staticmethod 装饰方法(比较难,需要理解)
@classmethod 用来修饰方法。使用在实例化前与类进行交互,但不和其实例进行交互的函数方法上。
@staticmethod 用来修饰类的静态方法。使用在有些与类相关函数,但不使用该类或该类的实例。如更改环境变量、修改其他类的属性等。
两者最明显的区别,classmethod 必须使用类的对象作为第一个参数,而staticmethod则可以不传递任何参数
类方法,我们不用通过实例化类就能访问的方法。而且@classmethod 装饰的方法不能使用实例属性,只能是类属性。它主要使用在和类进行交互,但不和其实例进行交互的函数方法上。
下面,我们要写一个只在类中运行而不在实例中运行的方法。
简单示例,读取私有化类属性数据,如下:
class Circle(object):
__pi = 3.14
def __init__(self, r):
self.r = r
@classmethod
def pi(cls):
return cls.__pi
def area(self):
"""
圆的面积
"""
return self.r ** 2 * self.__pi
print(Circle.pi()) # 没有实例化 能直接访问pi() 方法
circle1 = Circle(2)
print(circle1.pi()) # 也可以通过实例访问pi()方法
2、@staticmethod 静态方法
@staticmethod 和@classmethod非常的相似,但是@staticmethod 不强制要求传递参数(它做的事与类方法或实例方法一样)。
@staticmethod使用在有些和类相关函数,但不使用该类或者该类的实例。如更改环境变量、修改其他类的属性等。
一句话@staticmethod 修饰的方法是放在类外的函数,我们为了方便将他移动到了类里面,它对类的运行无影响。
三、Python 的 property 使用
property 的有两个作用
作为装饰器 @property 将类方法转换为类属性(只读)
property 重新实现一个属性的 setter 和 getter 方法
1、@property 将类方法转换为只读属性(常用)
使用 property 的最简单的方法是将它作为装饰器来使用。这可以让你将一个类方法转变成一个类属性。
示例:
class Circle(object):
__pi = 3.14
def __init__(self, r):
self.r = r
@property
def pi(self):
return self.__pi
circle1 = Circle(2)
print(circle1.pi)
circle1.pi=3.14159 # 出现AttributeError异常
上面示例装饰了pi方法,创建实例后我们可以使用circle1.pi 自己获取方法的返回值,而且他只能读不能修改。
那么什么是装饰器呢?
现在,假设我们要增强now()函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改now()函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。
本质上,decorator 就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的 decorator,可以定义如下:
def log(func):
def wrapper(*args, **kw):
print('call %s():' % func.__name__)
return func(*args, **kw)
return wrapper
@log
def now():
print('2015-3-25')
now()
# result:
# call now():
# 2015-3-25
把@log放到now()函数的定义处,相当于执行了语句: now = log(now)
由于log()是一个decorator,返回一个函数,所以,原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()函数中返回的wrapper()函数。
wrapper()函数的参数定义是(args, *kw),因此,wrapper()函数可以接受任意参数的调用。在wrapper()函数内,首先打印日志,再紧接着调用原始函数。
如果decorator本身需要传入参数,那就需要编写一个返回decorator的高阶函数,写出来会更复杂。比如,要自定义log的文本:
def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator
@log('execute')
def now():
print('2015-3-25')
now()
# execute now():
# 2015-3-25
和两层嵌套的decorator相比,3层嵌套的效果是这样的: now = log(‘execute’)(now)
请多多指教。
文章标题:Python Class 知识总结
本文作者:顺强
发布时间:2019-10-20, 23:59:00
原始链接:http://shunqiang.ml/python-pclass/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。