首页 技术 正文
技术 2022年11月11日
0 收藏 571 点赞 2,224 浏览 10292 个字

面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。

面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。

而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。

面向对象的编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。

  类就是一个模板,模板里可以包含多个函数,函数里实现一些功能

  对象则是根据模板创建的实例,通过实例对象可以执行类中的函数

Python 面向对象基础

  ·class 是关键字

  ·创建对象后面要加括号

面向对象举例

 class add:     def foo(self, a, b):
print("%s" % (a + b))
return 222222 obj = add()
c = obj.foo(1, 2)
print(c) class Bar: def foo(self, arg):
print(self, self.name, self.age, self.gender, arg) z = Bar()
z.name = "alex"
z.age = 84
z.gender = "zhong"
z.foo(666) z1 = Bar()
z1.name = "eric"
z1.age = 73
z1.gender = "nv"
z1.foo(699999)

面向对象三大特性

1.封装

封装就是把内容封到某个地方,供调用时使用

如例子

class Person:
def __init__(self, name, age):
self.n = name
self.a = age def show(self):
print("%s -%s" % (self.n, self.a))hu = Person("huxianglin", 25) # 创建对象
hu.show()liu = Person("dadd", 55) # 创建对象
liu.show()

self 是一个形式参数,当执行 hu = Person(“huxianglin”, 25)时,self 相当于 hu

self.name 这种形式叫做实例属性

当对象被创建时,先去寻找class中的__init__中的内容,存在则执行其中的内容,不存在则不执行。

继承

子类可以继承父类里面的各个方法,可以在子类中添加新的方法,或者用相同的函数名重写父类中用不到的方法。

class 子类(父类):

 class F:
def f1(self, b):
print("F.f1", b) def f2(self):
print("F.f2") class S(F): def s1(self):
print("S.s1") def f2(self):
super(S, self).f2()
print("S.f2")
F.f2(self) obj = S() obj.s1()
obj.f1(2)
obj.f2()

python可以继承多个父类,当调用一个方法时,先在子类中寻找,找不到则按顺序从左到右在父类中寻找。__init__也是如此。

继承的顺序:python3里面都是新式类,采用了C3算法。

先采用深度优先,当出现了一个交叉点时,则不在此点中寻找,而是重走交叉的另一条路,走到此点。

Python 面向对象基础

如图,E继承D,C

找寻顺序为D→B1→B2→B→C→A

若在运行时,父类中出现了新的方法,则从方法定义的类里重找,无论是多少级的父类。

 class BaseRequest:
pass class RequestHandler(BaseRequest): def sever_forever(self): print("RequestHandler.sever_forever")
self.process_request() # 重新回到Son里寻找,最后运行Minx里的procexx_request() def process_request(self):
print("RequestHandler.process_request") class Minx: def process_request(self):
print("minx.process_request") class Son(Minx, RequestHandler):
pass obj = Son()
obj.sever_forever()

多态

自带多态

进阶

 类的成员

类的成员分为三大类:字段、方法和属性。

其中静态字段叫做类属性。

字段包括:普通字段和静态字段。他们在定义和使用中有所区别,其最本质的区别是内存中保存的位置不同。

  ·普通字段属于对象

  ·静态字段属于类

 class Province:     # 静态字段,保存在类中
country = '中国' def __init__(self, name): # 普通字段,保存在对象中
self.name = name # 直接访问普通字段 , 通过对象访问
obj = Province('河北省')
print(obj.name) # 直接访问静态字段 ,通过类访问, 也可通过对象访问
Province.country 字段的定义和使用

普通字段在__init__下,静态字段不属于方法。

  ·静态字段在内存中值保存一份

  ·普通字段在每个对象中都要保存一份

应用场景:通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段。

方法

方法包括:普通方法、静态方法和类方法,三种方法在内存中都属于类,区别在于调用方式不同。

  ·普通方法:由对象调用,至少一个self参数,执行普通方法时,自动将调用该方法的对象赋值给self;

  ·类方法:由类调用,至少一个cls参数,执行类方法时,自动将调用该方法的类复制给cls;

  ·静态方法:由类调用,无默认参数

 class Foo:     def __init__(self, name):
self.name = name def ord_func(self):
""" 定义普通方法,至少有一个self参数 """ # print self.name
print('普通方法') @classmethod
def class_func(cls):
""" 定义类方法,至少有一个cls参数
cls是类名,保存在类中
       """ print('类方法') @staticmethod
def static_func():
""" 定义静态方法 ,无默认参数""" print('静态方法') # 调用普通方法
f = Foo()
f.ord_func() # 调用类方法
Foo.class_func() # 调用静态方法
Foo.static_func() 方法的定义和使用

对于所有的方法而言,均属于类中,在内存中也只保存一份。

属性

属性是普通方法的变种。

1.属性的基本使用

 # ############### 定义 ###############
class Foo: def func(self):
pass # 定义属性
@property
def prop(self):
pass
# ############### 调用 ###############
foo_obj = Foo() foo_obj.func()
foo_obj.prop #调用属性 属性的定义和使用

定义时,在普通方法上添加@property装饰器

定义时,属性仅有一个self参数

调用时,无需括号

  方法: foo_obj.fun()

  属性: foo_obj.prop

 class Pergination:
def __init__(self, current_page):
try:
p1 = int(current_page)
except Exception as e:
p1 = 1 self.page = p1 @property
def start(self):
val = (self.page - 1) * 10
return val @property
def end(self):
val2 = self.page * 10
return val2 li = []
for i in range(1000):
li.append(i) while True:
p = input("请输入要查看的页码:")
obj = Pergination(p)
print(li[obj.start: obj.end])

2.属性的两种定义方式

  装饰器:在方法上应用装饰器

  静态字段 : 在类定义值为property对象的静态字段

装饰器方式:在类的普通方法上应用@property装饰器

 class Goods(object):     def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8 @property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price @price.setter
def price(self, value):
self.original_price = value @price.deltter
def price(self, value):
del self.original_price obj = Goods()
obj.price # 获取商品价格
obj.price = 200 # 修改商品原价
del obj.price # 删除商品原价 # 与删除操作无关,只对应@price.deltter

静态字段方式,创建值为property的对象的静态字段

 class Foo:     def get_bar(self):
return 'wupeiqi' BAR = property(get_bar) obj = Foo()
reuslt = obj.BAR # 自动调用get_bar方法,并获取方法的返回值
print(reuslt)

property的构造方法中有个四个参数

  • 第一个参数是方法名,调用 对象.属性时自动触发执行方法
  • 第二个参数是方法名,调用对象.属性 = XXX 时自动触发执行方法
  • 第三个参数是方法名,调用del 对象.属性 时自动触发执行方法
  • 第四个参数是字符串,调用对象.属性.__doc__ ,此参数是该属性的描述信息
 class Foo:     def get_bar(self):
return 'wupeiqi' # *必须两个参数
def set_bar(self, value):
return return 'set value' + value def del_bar(self):
return 'wupeiqi' BAR = property(get_bar, set_bar, del_bar, 'description...') obj = Foo() obj.BAR # 自动调用第一个参数中定义的方法:get_bar
obj.BAR = "alex" # 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
del Foo.BAR # 自动调用第三个参数中定义的方法:del_bar方法
obj.BAE.__doc__ # 自动获取第四个参数中设置的值:description...

 成员修饰符

前面带两个_的为私有成员,外部无法直接访问

 class Foo:     def __init__(self, name, age):
self.name = name
# self.age = age
self.__age = age # 私有,外部无法直接访问 def show(self):
return self.__age obj = Foo('alex', 19)
print(obj.name)
# obj.age
# print(obj.__age)
ret = obj.show()
print(ret)
 class Foo:
__v = '' def __init__(self):
pass
def show(self):
return Foo.__v
@staticmethod
def stat():
return Foo.__v
# print(Foo.__v)
# ret = Foo().show()
# print(ret) ret = Foo.stat()
print(ret)

2

 class Foo:
def __f1(self):
return 123 def f2(self):
r = self.__f1()
return r obj = Foo()
ret = obj.f2()
print(ret)

3

 类的特殊成员

1.__init__

构造方法,创建对象时自动执行

2.__del__

析构方法,当对象在内存中被释放时自动执行

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的。

class Foo:    def __del__(self):
pass

__del__

3.__call__

对象后面加括号触发执行

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

 class Foo:     def __init__(self):
pass def __call__(self, *args, **kwargs): print '__call__' obj = Foo() # 执行 __init__
obj() # 执行 __call__

__call__

 class Entity:     def __init__(self, size, x, y):
self.size = size
self.x = x
self.y = y
print(self.x, self.y) def __call__(self, x, y):
self.x, self.y = x, y
obj = Entity(6, 8, 9) obj(10, 19)
print(obj.x, obj.y)
# 10 19
# x和y的值改变了

应用

4.__int__、__str__

如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。

 class Foo:     def __init__(self,n,a):
self.name =n
self.age =a def __str__(self):
return '%s-%s' %(self.name,self.age,) obj = Foo('alex', 18)
print(obj) #print(str(obj)) str(obj) obj中__str__,并获取其返回值

__str__

int,对象,自动执行对象的 __int__方法,并将返回值赋值给int对象

 class Foo:     def __init__(self):
pass def __int__(self):
return 1111 def __str__(self):
return 'alex' obj = Foo()
print(obj, type(obj)) # int,对象,自动执行对象的 __int__方法,并将返回值赋值给int对象
r = int(obj)
print(r)
i = str(obj)
print(i)
"""
输出为
alex <class '__main__.Foo'>
1111
alex
"""

__int__

5.__add__

两个对象相加时,自动执行第一个对象的的 __add__方法,并且将第二个对象当作参数传递进入
 class Foo:     def __init__(self, name, age):
self.name = name
self.age = age def __add__(self, other):
# self = obj1 (alex,19)
# other = obj2(eric,66)
# return self.age + other.age
#return Foo('tt',99)
return Foo(self.name, other.age) # def __del__(self):
# print('析构方法') # 对象被销毁()时,自动执行 obj1 = Foo('alex', 19)
obj2 = Foo('eirc', 66) r = obj1 + obj2
# 两个对象相加时,自动执行第一个对象的的 __add__方法,并且将第二个对象当作参数传递进入
print(r, type(r))
print(r.name, r.age)
'''
输出为
<__main__.Foo object at 0x000001F81BD29390> <class '__main__.Foo'>
alex 66
'''

__add__

6.__dict__

类的普通字段属于对象;类中的静态字段和方法等属于类

将对象中所封装的元素通过字典的形式返回

 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__)
# 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None} obj1 = Province('HeBei',10000)
print(obj1.__dict__)
# 获取 对象obj1 的成员
# 输出:{'count': 10000, 'name': 'HeBei'} obj2 = Province('HeNan', 3888)
print(obj2.__dict__)
# 获取 对象obj1 的成员
# 输出:{'count': 3888, 'name': 'HeNan'}

__dict__

7.__getitem__、__setitem__、__delitem__

用于索引操作,如字典、列表

 class Foo(object):
def __getitem__(self, key):
print('__getitem__', key) def __setitem__(self, key, value):
print('__setitem__', key, value) def __delitem__(self, key):
print('__delitem__', key) obj = Foo() result = obj[0] # 自动触发执行 __getitem__
obj[1] = 'wupeiqi' # 自动触发执行 __setitem__
del obj[2] # 自动触发执行 __delitem__
 class Foo:     def __init__(self, name,age):
self.name = name
self.age = age def __getitem__(self, item):
# return item+10
# 如果item是基本类型:int,str,索引获取
# slice对象的话,切片
if type(item) == slice:
print('调用这希望内部做切片处理')
else:
print(item.start)
print(item.stop)
print(item.step)
print('调用这希望内部做索引处理') def __setitem__(self, key, value):
print(key, value) def __delitem__(self, key):
print(key) li = Foo('alex', 18)
# li[123]
li[1:4:2] li[1:3] = [11, 22] del li[1: 3]
'''
输出为
调用这希望内部做切片处理
slice(1, 3, None) [11, 22]
slice(1, 3, None)
'''

2

8.__iter__

如果类中有 __iter__ 方法,对象=》可迭代对象
对象.__iter__() 的返回值: 迭代器
for 循环,迭代器,next
for 循环,可迭代对象,对象.__iter__(),迭代器,next
1、执行li对象的类F类中的 __iter__方法,并获取其返回值
2、循环上一步中返回的对象

元类

a. Python中一切事物都是对象
b.
class Foo:
pass
obj = Foo()
# obj是对象,Foo类
# Foo类也是一个对象,type的对象

c.
类都是type类的对象 type(..)
“对象”都是以类的对象 类()

创建类的另一种方法:通过type的构造函数

 def func(self):
print('hello wupeiqi') Foo = type('Foo', (object,), {'func': func})
# type第一个参数:类名
# type第二个参数:当前类的基类
# type第三个参数:类的成员
a = Foo()
a.func()

类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

Python 面向对象基础

class MyType(type):    def __init__(self, what, bases=None, dict=None):
super(MyType, self).__init__(what, bases, dict) def __call__(self, *args, **kwargs):
obj = self.__new__(self, *args, **kwargs) self.__init__(obj)class Foo: __metaclass__ = MyType def __init__(self, name):
self.name = name def __new__(cls, *args, **kwargs):
return "对象"# 第一阶段:解释器从上到下执行代码创建Foo类
# 第二阶段:通过Foo类创建obj对象
obj = Foo("xiaoming") # Foo由MyType创建,所以,Foo()先执行MyType()中的__call__

 通过字符串操作对象中的成员getattr(),hasattr(),setattr(),delattr()

hasattr(object, name)

判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。

name要加引号

 >>> class test():
... name="xiaohua"
... def run(self):
... return "HelloWord"
...
>>> t=test()
>>> hasattr(t, "name") #判断对象有name属性
True
>>> hasattr(t, "run") #判断对象有run方法
True
>>>

getattr(object, name[, default])

获取对象object的属性或者方法,如果存在打印出来,如果不存在,打印出默认值,默认值可选。
需要注意的是,如果是返回的对象的方法,返回的是方法的内存地址,如果需要运行这个方法,
可以在后面添加一对括号。

 >>> class test():
... name="xiaohua"
... def run(self):
... return "HelloWord"
...
>>> t=test()
>>> getattr(t, "name") #获取name属性,存在就打印出来。
'xiaohua'
>>> getattr(t, "run") #获取run方法,存在就打印出方法的内存地址。
<bound method test.run of <__main__.test instance at 0x0269C878>>
>>> getattr(t, "run")() #获取run方法,后面加括号可以将这个方法运行。
'HelloWord'
>>> getattr(t, "age") #获取一个不存在的属性。
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: test instance has no attribute 'age'
>>> getattr(t, "age","") #若属性不存在,返回一个默认值。
''
>>>

setattr(object, name, values)

给对象的属性赋值,若属性不存在,先创建再赋值。

 >>> class test():
... name="xiaohua"
... def run(self):
... return "HelloWord"
...
>>> t=test()
>>> hasattr(t, "age") #判断属性是否存在
False
>>> setattr(t, "age", "") #为属相赋值,并没有返回值
>>> hasattr(t, "age") #属性存在了
True
>>>

delattr(object, name)

删除对象的属性

综合应用

 >>> class test():
... name="xiaohua"
... def run(self):
... return "HelloWord"
...
>>> t=test()
>>> getattr(t, "age") #age属性不存在
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: test instance has no attribute 'age'
>>> getattr(t, "age", setattr(t, "age", "")) #age属性不存在时,设置该属性
''
>>> getattr(t, "age") #可检测设置成功
''
>>>
相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,955
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,479
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,291
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,108
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,740
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,774