Python 面向对象编程
为了更好的理解面向对象编程,请继续(类似 Java)
常见步骤:
- 导入各种外部库
- 设计各种全局变量
- 决定你要的类
- 给每个类提供完整的一组操作
- 明确地使用继承来表现不同类之间的共同点
- 根据需要,决定是否写一个 main 函数作为程序入口
面向对象编程中,将函数和变量进一步封装成类,类才是程序的基本元素,它将数据和操作紧密地连结在一起,并保护数据不会被外界的函数意外地改变。类和和类的实例(也称对象)是面向对象的核心概念,是和面向过程编程、函数式编程的根本区别。
并不是非要用面向对象编程,要看你的程序怎么设计方便,但是就目前来说,基本上都是在使用面向对象编程。
类的基本用法
面向对象是通过定义 class 类来定义,这么说面向对象编程就是只使用 class 类,在 class 类中有封装,继承的功能,并且还可以构造要传入的参数,方便控制。 、
import sys
import time
reload(sys)
sys.setdefaultencoding('utf-8')
class studetn:
# 定义一个类名为 studetn
def __init__(self,idx):
# 定义初始化构造,这里使用 init,还有别的属性比如 reversed,iter 之类的
self.idx=idx
# 初始化变量,方便继承
def runx(self):
# 定义运行函数,从上面继承变量
print self.idx
# 打印出 idx 的值,或者做一些别的处理
time.sleep(1)
a=studetn('a')
a.runx()
# 这是类的调用,一定要记得类的使用方法,首先传入参数,类赋值给一个变量 a
# 然后调用这个类下面定义的函数
1、类(Class): 用来描述具有相同属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。其中的对象被称作类的实例。
2、实例:也称对象。通过类定义的初始化方法,赋予具体的值,成为一个”有血有肉的实体”。
3、实例化:创建类的实例的过程或操作。
4、实例变量:定义在实例中的变量,只作用于当前实例。
5、类变量:类变量是所有实例公有的变量。类变量定义在类中,但在方法体之外。
6、数据成员:类变量、实例变量、方法、类方法、静态方法和属性等的统称。
7、方法:类中定义的函数。
8、静态方法:不需要实例化就可以由类执行的方法。
9、类方法:类方法是将类本身作为对象进行操作的方法。
10、方法重写:如果从父类继承的方法不能满足子类的需求,可以对父类的方法进行改写,这个过程也称 override。
11、封装:将内部实现包裹起来,对外透明,提供 api 接口进行调用的机制。
12、继承:即一个派生类(derived class)继承父类(base class)的变量和方法。
13、多态:根据对象类型的不同以不同的方式进行处理。
类与实例
# -*- conding: utf-8 -*-
# @Author:暗香彻骨.沐之杰 (Hugo)
# @Contact : qyx01@qq.com
# @Time: 2019/2/1 9:34
# @Software: PyCharm
# @File: 类与实例.py
# @Description:
import sys
import time
import requests
reload(sys)
sys.setdefaultencoding('utf-8')
class cc:
ccc = 'ccc'
# cc 就是类名 如果想要继承别的类 就 class cc(threading) 意思就是从 threading 继承
def __init__(self,a,b,c):
self.a=a
self.b=b
self.c=c
# 定义构造的过程就是实例化
def runx(self):
print self.a*10
print self.b*5
print self.c*2
def runy(self):
print requests.get('http://www.langzi.fun').headers
e = cc('AAA','CCC','EEE')
e.runx()
e.runy()
# 这两个就是调用类里面的方法
print e.c
#实例变量指的是实例本身拥有的变量。每个实例的变量在内存中都不一样。
print e.ccc
#类变量,在类里面找到定义的变量。
调用类的三种方法
1、实例方法
import sys
import time
import requests
reload(sys)
sys.setdefaultencoding('utf-8')
class dd:
def __init__(self,url):
self.url=url
def runx(self):
print requests.get(self.url).status_code
a = dd('http://www.langzi.fun')
a.runx()
# 这种调用方法就是实例方法
2、静态方法
静态方法由类调用,无默认参数。将实例方法参数中的 self 去掉,然后在方法定义上方加上 @staticmethod,就成为静态方法。它属于类,和实例无关。建议只使用类名.静态方法的调用方式。
import sys
import requests
reload(sys)
sys.setdefaultencoding('utf-8')
class ff:
@staticmethod
def runx():
print requests.get('http://www.langzi.fun').status_code
ff.runx()
#这里就直接调用了类的变量,只在类中运行而不在实例中运行的方法
2、类方法
类方法由类调用,采用 @classmethod 装饰,至少传入一个 cls(代指类本身,类似 self)参数。执行类方法时,自动将调用该方法的类赋值给 cls。建议只使用类名.类方法的调用方式。
import sys
import requests
reload(sys)
sys.setdefaultencoding('utf-8')
class gg:
url = 0
stat = 0
# 因为使用 classmethod 后会传入新的变量,所以一开始是需要自己先定义类变量
def __init__(self,url=0,stat=0):
# 这里按照正常的定义构造函数
self.url=url
self.stat=stat
@classmethod
# 装饰器,立马执行下面的函数
def split(cls,info):
# 这个函数接受两个参数,默认的 cls 就是这个类的 init 函数,info 就是外面传入进来的
url,stat=map(str,info.split('-'))
# 这里转换成了格式化的结构
data = cls(url,stat)
# 然后执行这个类第一个方法,这个类构造函数需要传入两个参数,于是就传入了两个参数
return data
# 这里就直接返回了函数结果
def outer(self):
print self.url
print self.stat
r = gg.split(('langzi-200'))
r.outer()
# 这里是调用类方法,与调用实例方法一样
类的特性
封装
封装是指将数据与具体操作的实现代码放在某个对象内部,外部无法访问。必须要先调用类的方法才能启动。
class cc:
ccc = 'ccc'
# cc 就是类名 如果想要继承别的类 就 class cc(threading) 意思就是从 threading 继承
def __init__(self,a,b,c):
self.a=a
self.b=b
self.c=c
print e.ccc
#类变量,在类里面找到定义的变量。
print ccc
# 这里会报错,这就是封装。类中的函数同理。
继承
当我们定义一个 class 的时候,可以从某个现有的 class 继承,新的 class 称为子类(Subclass),而被继承的 class 称为基类、父类或超类(Base class、Super class)。
比如,我们已经编写了一个名为 Animal 的 class,有一个 run() 方法可以直接打印:
class Animal(object):
def run(self):
print 'Animal is running...'
当我们需要编写 Dog 和 Cat 类时,就可以直接从 Animal 类继承:
class Dog(Animal):
pass
class Cat(Animal):
pass
继承有什么好处?最大的好处是子类获得了父类的全部功能。由于 Animial 实现了 run() 方法,因此,Dog 和 Cat 作为它的子类,什么事也没干,就自动拥有了 run() 方法:
dog = Dog()
dog.run()
cat = Cat()
cat.run()
当子类和父类都存在相同的 run() 方法时,我们说,子类的 run() 覆盖了父类的 run(),在代码运行的时候,总是会调用子类的 run()。这样,我们就获得了继承的另一个好处:多态。
多态
要理解多态的好处,我们还需要再编写一个函数,这个函数接受一个 Animal 类型的变量:
def run_twice(animal):
animal.run()
animal.run()
当我们传入 Animal 的实例时,run_twice() 就打印出:
run_twice(Animal())
运行结果:
Animal is running...
Animal is running...
当我们传入 Dog 的实例时,run_twice() 就打印出:
run_twice(Dog())
运行结果:
Dog is running...
Dog is running...
当我们传入 Cat 的实例时,run_twice() 就打印出:
run_twice(Cat())
运行结果:
Cat is running...
Cat is running...
现在,如果我们再定义一个 Tortoise 类型,也从 Animal 派生:
class Tortoise(Animal):
def run(self):
print 'Tortoise is running slowly...'
当我们调用 run_twice() 时,传入 Tortoise 的实例:
run_twice(Tortoise())
运行结果:
Tortoise is running slowly...
Tortoise is running slowly...
你会发现,新增一个 Animal 的子类,不必对 run_twice() 做任何修改,实际上,任何依赖 Animal 作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。多态的好处
就是,当我们需要传入 Dog、Cat、Tortoise……时,我们只需要接收 Animal 类型就可以了,因为 Dog、Cat、Tortoise……都是 Animal 类型,然后,按照 Animal 类型进行操作即可。由于 Animal 类型有 run() 方法,因此,传入的任意类型,只要是 Animal 类或者子类,就会自动调用实际类型的 run() 方法,这就是多态的意思:
对于一个变量,我们只需要知道它是 Animal 类型,无需确切地知道它的子类型,就可以放心地调用 run() 方法,而具体调用的 run() 方法是作用在 Animal、Dog、Cat 还是 Tortoise 对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种 Animal 的子类时,只要确保 run() 方法编写正确,不用管原来的代码是如何调用的。这就是著名的 开闭 原则:
对扩展开放:允许新增 Animal 子类;
对修改封闭:不需要修改依赖 Animal 类型的 run_twice() 等函数。
总结:继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写;有了继承,才能有多态。在调用类实例方法的时候,尽量把变量视作父类类型,这样,所有子类类型都可以正常被接收;
旧的方式定义 Python 类允许不从 object 类继承,但这种编程方式已经严重不推荐使用。任何时候,如果没有合适的类可以继承,就继承自 object 类。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Python Pandas 入门
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论