类是面向对象编程的基础,是python开发过程中需要重要掌握的知识点。
在面向对象编程中,一个对象就是一个类;一个对象有不同的属性,有不同动作或者功能项,相应的类也有不同的属性和函数。
类的作用就是将一个对象的功能和属性完整的内聚在一个类中; 如果功能和属性零散的分布在不同的地方,没有一个清晰的功能,代码结构也凌乱。
1.类的基础使用
我们来看看python中类的定义和使用
class Person(object):
def __init__(self, name, age):
self.name = name
self.age = age
self.interest_names = []
def add_interest(self, interest_name):
self.interest_names.append(interest_name)
print('{} like {}'.format(self.name, self.interest_names))
jack = Person(name='jack', age=10)
jack.add_interest('football')
jack.info = "haha"
# jack like ['football']
jack.name, jack.age, jack.info
#('jack', 10, 'haha')
从上面可知,通过class
关键字来创建类,默认的所有的类的父类为object;
- 通过
__init__
来初始化类信息,通过self设置可通过类的实例访问的属性 - 类创建完,通过实例化来获取类的实例如jack是Person的实例化
- 实例化可直接访问self的属性和类的方法
那python中类的属性或者变量有公有和私有变量?
答案是:Python中没有禁止访问类中某一成员的保护机制;python通过约定的方式来实现公有和私有变量,通常以下划线开头的变量和方法都不允许外部访问和修改即私有方法。
值得注意的是:以双下划线开头且以至多一个下划线结尾的成员变量或方法,会进行名称转写,如__var_, 也就是如果直接访问__var_, 会报没有这个属性的错误
class Person(object):
data = "public"
__private_ = 'private'
def __init__(self, name, age):
self.name = name
self.age = age
self.interest_names = []
self._data2 = 'not public'
self.__private = "private check"
def add_interest(self, interest_name):
self.interest_names.append(interest_name)
print(self.data, self._data2)
print('{} like {}'.format(self.name, self.interest_names))
jack = Person(name='jack', age=10)
jack.add_interest('football')
print(jack._data2)
print(jack.__private)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-26-9b8a1b0fa383> in <module>()
2 jack.add_interest('football')
3 print(jack._data2)
----> 4 print(jack.__private)
AttributeError: 'Person' object has no attribute '__private'
可见加了一个下划线的,还是可以访问的。但是如果是__private_
会报错,因为python进行了强制转写为_Person__private
,要访问需要jack._Person__private_
就可以访问,这一定程度上屏蔽了外部的使用的这个变量。
可以通多dir(jack)
看出jack实例化所拥有的变量和方法
dir(jack)
['_Person__private',
'__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'_data2',
'add_interest',
'age',
'data',
'interest_names',
'name']
2.继承
继承是类的重要特点,子类通过继承可以继承父类的方法和变量,同时也可以重写父类的方法等。上面提到默认所有的类都继承object大类。
下面我们来编写前面写的Person类的子类:工程师类Engineer
class Engineer(Person):
def __init__(self, name, age):
# super.__init__(name, age)
super(Engineer, self).__init__(name, age)
def do_task(self, task_name):
print('{} do {}'.format(self.name, task_name))
e = Engineer('john', 30)
e.add_interest('program')
e.do_task('do task')
print(e.name, e.age)
# public not public
# john like ['program']
# john do do task
# john 30
从上面可知,子类继承父类的特点:
- 可以通过super关键字获取父类,并进行父类的初始化
- 子类的实例化可以直接调到父类的方法和变量
继承的好处:
- 子类是父类的扩展,不同的子类可以复用父类的方法,使得编程简洁
3.抽象类
这个小节我们来介绍一个特殊的类:抽象类;与一般的类相比,抽象类的特点:
- 抽象类只能继承,不能实例化
- 继承抽象类中的子类,必须重写抽象类的方法(强制的)
- 抽象类类似接口,子类是接口的的实现
- 抽象类要求子类必须实现里面的方法,所以经常用于框架开发中,是对某些具体的任务的抽象;比如数据处理需要经过1.获取数据2.数据处理3.保存数据等步骤,可以定义数据处理的抽象,在写不同的数据处理任务时,可以按照这个流程来走,规范开发。
接着,我们来看看python中抽象类吧。
import abc
class Task(metaclass=abc.ABCMeta):
@abc.abstractmethod
def pre_process_data(self):
pass
@abc.abstractmethod
def do_task(self):
pass
@abc.abstractmethod
def output_data(self):
pass
import cv2
import random
import numpy as np
import matplotlib.pyplot as plt
class AugmentationImage(Task):
def __init__(self, img_file):
self.img_file = img_file
self.img = None
def pre_process_data(self):
self.img = cv2.imread(self.img_file)
h, w, c = self.img.shape
print(h, w, c)
start_h = random.sample(range(h//5), 1)[0]
start_w = random.sample(range(w//5), 1)[0]
self.img = self.img[start_h: start_h+244, start_w: start_w+244]
def do_task(self, mul_=1.1):
self.img = np.clip(self.img * mul_, 0, 255).astype(np.uint8)
def output_data(self, output_filename='test.output.jpg'):
cv2.imwrite(output_filename, self.img)
从上面可知,
- python利用abc模块实现抽象类
- AugmentationImage子类继承了抽象类,来实现图像增强(随机crop和像素变换)
- 必须继承抽象基类中方法(通过定义@abc.abstractmethod)
- 子类中实现的方法参数可以自定义变化,不一定和抽象类相同,但是名称必须相同
4.总结
本文分享了python中类的最基本和最重要的知识,希望对你有帮助。总结如下:
- 如果你觉得你的代码写的太乱,一种是选择类的内聚你的功能;当然还有模块化和函数化两件法宝
- 关键字:class申明类,__init__来初始化类,self定义类内和实例化可访问的方法和属性,super获取父类,abc实现抽象类
- 公有和私有变量:python没有从语法上强制变量的访问约束,都是公有的; python采用约定方式来实现变量的访问界定,注意下划线在python中的特定含义;_var一般约定为私有变量,另外注意两个前置下划线__var,python解释器会进行强制转写。
- 善用类的继承特性,简洁你的代码
- 抽象类来规划你流程:抽象类的子类必须实现父类的抽象方法。