python 面向对象编程
面向对象编程中,将函数和变量进一步封装成类,类才是程序的基本元素,它将数据和操作紧密地连结在一起,并保护数据不会被外界的函数意外地改变。类和和类的实例(也称对象)是面向对象的核心概念
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
# 然后调用这个类下面定义的函数
一些专业术语概念,既然有面向对象编程这个高大上的定义了,自然要搭配一些高大上的概念。
- 类(Class): 用来描述具有相同属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。其中的对象被称作类的实例。
- 实例:也称对象。通过类定义的初始化方法,赋予具体的值,成为一个”有血有肉的实体”。
- 实例化:创建类的实例的过程或操作。
- 实例变量:定义在实例中的变量,只作用于当前实例。
- 类变量:类变量是所有实例公有的变量。类变量定义在类中,但在方法体之外。
- 数据成员:类变量、实例变量、方法、类方法、静态方法和属性等的统称。
- 方法:类中定义的函数。
- 静态方法:不需要实例化就可以由类执行的方法
- 类方法:类方法是将类本身作为对象进行操作的方法。
- 方法重写:如果从父类继承的方法不能满足子类的需求,可以对父类的方法进行改写,这个过程也称override。
- 封装:将内部实现包裹起来,对外透明,提供api接口进行调用的机制
- 继承:即一个派生类(derived class)继承父类(base class)的变量和方法。
- 多态:根据对象类型的不同以不同的方式进行处理。
类与实例
import sys
import time
import requests
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(('http://www.langzi.fun'))
e = cc('AAA','CCC','EEE')
e.runx()
'''
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
CCCCCCCCCCCCCCC
EEEEEE
'''
e.runy() #http://www.langzi.fun
# 这两个就是调用类里面的方法
print(e.c) #EEE
#实例变量指的是实例本身拥有的变量。每个实例的变量在内存中都不一样。
print(e.ccc) #ccc
#类变量,在类里面找到定义的变量。
调用类的三种方法
实例方法
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()
# 这种调用方法就是实例方法
静态方法
静态方法由类调用,无默认参数。将实例方法参数中的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()
#这里就直接调用了类的变量,只在类中运行而不在实例中运行的方法
经常有一些跟类有关系的功能但在运行时又不需要实例和类参与的情况下需要用到静态方法. 比如更改环境变量或者修改其他类的属性等能用到静态方法. 这种情况可以直接用函数解决, 但这样同样会扩散类内部的代码,造成维护困难。
类方法
类方法由类调用,采用@classmethod
装饰,至少传入一个cls
代指类本身,类似self)参数。执行类方法时,自动将调用该方法的类赋值给cls。建议只使用类名.类方法的调用方式。(虽然也可以使用实例名.类方法的方式调用)
如果要构造一个类,接受一个网站和这个网站的状态码,然后打印出来。就像这样:
import sys
import requests
reload(sys)
sys.setdefaultencoding('utf-8')
class gg:
def __init__(self,url,stat):
self.url=url
self.stat=stat
def outer(self):
print self.url
print self.stat
a = gg('langzi',200)
a.outer()
这样就是使用实例方法,虽然可以实现,但是有的时候传入的参数并不是(‘langzi’,200)这样的格式,而是(‘langzi-200’)这样的,那该怎么做?首先要把这个拆分,但是要使用实例方法实现起来很麻烦,这个时候就可以使用类方法。
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()
# 这里是调用类方法,与调用实例方法一样
魔法方法
在上面有提到除了init之外还有iter,reverse的方法,这里就详细说下除了init初始化还有哪些别的方法。
__init__ : 构造函数,在生成对象时调用
__del__ : 析构函数,释放对象时使用
__repr__ : 打印,转换
__setitem__ : 按照索引赋值
__getitem__: 按照索引获取值
__len__: 获得长度
__cmp__: 比较运算
__call__: 调用
__add__: 加运算
__sub__: 减运算
__mul__: 乘运算
__div__: 除运算
__mod__: 求余运算
__pow__: 幂
具体使用
1. doc
说明性文档和信息。Python自建,无需自定义。
class Foo:
""" 描述类信息,可被自动收集 """
def func(self):
pass
# 打印类的说明文档
print(Foo.__doc__)
2. init()
实例化方法,通过类创建实例时,自动触发执行。
class Foo:
def __init__(self, name):
self.name = name
self.age = 18
obj = Foo(jack') # 自动执行类中的 __init__ 方法
3. __module__和 __class__
module 表示当前操作的对象在属于哪个模块。 class 表示当前操作的对象属于哪个类。 这两者也是Python内建,无需自定义。
class Foo:
pass
obj = Foo()
print(obj.__module__)
print(obj.__class__)
运行结果:
main
4. __del()__
析构方法,当对象在内存中被释放时,自动触发此方法。
注:此方法一般无须自定义,因为Python自带内存分配和释放机制,除非你需要在释放的时候指定做一些动作。析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。
class Foo:
def __del__(self):
print("我被回收了!")
obj = Foo()
del obj
5. call()
如果为一个类编写了该方法,那么在该类的实例后面加括号,可会调用这个方法。
注:构造方法的执行是由类加括号执行的,即:对象 = 类名(),而对于call() 方法,是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:
def __init__(self):
pass
def __call__(self, *args, **kwargs):
print('__call__')
obj = Foo() # 执行 __init__
obj() # 执行 __call__
可以用Python内建的callable()函数进行测试,判断一个对象是否可以被执行。
callable(Student()) 运行结果:
True
6. dict
列出类或对象中的所有成员!非常重要和有用的一个属性,Python自建,无需用户自己定义。
class Province:
country = 'China'
def __init__(self, name, count):
self.name = name
self.count = count
def func(self, *args, **kwargs):
print('func')
# 获取类的成员
print(Province.__dict__)
# 获取 对象obj1 的成员
obj1 = Province('HeBei',10000)
print(obj1.__dict__)
# 获取 对象obj2 的成员
obj2 = Province('HeNan', 3888)
print(obj2.__dict__)
7. str()
如果一个类中定义了str()方法,那么在打印对象时,默认输出该方法的返回值。这也是一个非常重要的方法,需要用户自己定义。
下面的类,没有定义str()方法,打印结果是
class Foo:
pass
obj = Foo()
print(obj)
定义了__str__()方法后,打印结果是:'jack'。
class Foo:
def __str__(self):
return 'jack'
obj = Foo()
print(obj) #jack
8、getitem()、setitem()、delitem()
取值、赋值、删除这“三剑客”的套路,在Python中,我们已经见过很多次了,比如前面的@property装饰器。
Python中,标识符后面加圆括号,通常代表执行或调用方法的意思。而在标识符后面加中括号[],通常代表取值的意思。Python设计了getitem()、setitem()、delitem()这三个特殊成员,用于执行与中括号有关的动作。它们分别表示取值、赋值、删除数据。