Python 面向对象基础
面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
面向对象的编程方式的落地需要使用 “类” 和 “对象” 来实现,所以,面向对象编程其实就是对 “类” 和 “对象” 的使用。
类就是一个模板,模板里可以包含多个函数,函数里实现一些功能
对象则是根据模板创建的实例,通过实例对象可以执行类中的函数
·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算法。
先采用深度优先,当出现了一个交叉点时,则不在此点中寻找,而是重走交叉的另一条路,走到此点。
如图,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类的派生类,从而查看 类 创建的过程。
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 面向对象 基础
编程范式概述:面向过程 和 面向对象 以及函数式编程 面向过程:(Procedure Oriented)是一种以事件为中心的编程思想. 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现 ...
- python面向对象基础
面向对象基础 1. 简述 编程方式: 面向过程: 根据代码在脚本的堆叠顺序,从上到下依次执行 函数式编程:将相同功能的代码封装到函数中,直接调用即可,减少代码重复性 面向对象:对函数进行分类和封装,将 ...
- Python 面向对象基础知识
面向对象基础知识 1.什么是面向对象编程? - 以前使用函数 - 类 + 对象 2.什么是类什么是对象,又有什么关系? class 类: def 函数1(): pass def 函数2(): pass ...
- python 面向对象基础和高级复习
面向对象基础 面向对象编程 面向过程编程:类似于工厂的流水线 优点:逻辑清晰 缺点:扩展性差 面向对象编程:核心是对象二字,对象属性和方法的集合体,面向对象编程就是一堆对象交互 优点:扩展性强 缺点: ...
- 十六、python面向对象基础篇
面向对象基础: 在了解面向对象之前,先了解下变成范式: 编程范式是一类典型的编程风格,是一种方法学 编程范式决定了程序员对程序执行的看法 oop中,程序是一系列对象的相互作用 python支持多种编程 ...
- 1.Python面向对象基础
面向对象(OOP) 面向对象编程--object oriented programming 简写 OOP 面向过程和面向对象的区别: 面向过程: 1.把完成某一个需求的所有步骤从头到尾逐步实现 2 ...
- [python面向对象]--基础篇
1.#类 #类就是一个模板,模板里可以包含多个函数,函数里实现一些功能 #定义一个类 class bar: def foo(self,agr): print(self,agr) obj = bar() ...
- Python面向对象基础:编码细节和注意事项
在前面,我用了3篇文章解释python的面向对象: 面向对象:从代码复用开始 面向对象:设置对象属性 类和对象的名称空间 本篇是第4篇,用一个完整的示例来解释面向对象的一些细节. 例子的模型是父类Em ...
- Python面向对象基础一
公司可能过一两个月就要从深圳搬到东莞松山湖,项目组的现在有的在转Java或其他语言的,问我们要不要转java+hoodap+spark方向,我还是先不转,毕竟之前是从ios转回C#,这现在在转其他的那 ...
- python面向对象基础-01
面向对象(OOP)基本概念 前言 话说三国时期曹军于官渡大败袁绍,酒席之间,曹操诗兴大发,吟道:喝酒唱歌,人生真爽! 众将直呼:"丞相好诗",于是命印刷工匠刻板印刷以流传天下; 待 ...
随机推荐
- SQL生成随机字符串
1.SQLserve生成随机字符串 SELECT replace(newid(), '-', '')
- Linux 块设备驱动 (二)
linux下Ramdisk驱动 1 什么是Ramdisk Ramdisk是一种模拟磁盘,其数据实际上是存储在RAM中,它使用一部分内存空间来模拟出一个磁盘设备,并以块设备的方式来组织和访问这片内存.对 ...
- discuz!NT 常用操作
一.编辑模版,需在后台模版管理里编辑并提交,这样系统能批量更改相关模版.如:更改登录. 二.config.a 表明:config表示配置文件,a表示配置节名称为a,需在路径 upload_files\ ...
- OpenReports中文支持方案
此文章在<OpenReports中文支持完全解决方案.doc>的基础上做优化,并贴出代码.已测试通过. 一.主要解决的问题 1 页面显示支持中文 2 与服务器或数据库的交互支持中文 3 查 ...
- JUnit4中的测试套件
测试套件 JUnit3.8中,用测试套件同时运行多个测试类(http://www.cnblogs.com/mengdd/archive/2013/04/07/3006265.html). 在JUnit ...
- 数据库中简单的增删改查(CRUD)
一切都是基于数据,而对数据的管理都离不开数据库.最近学到数据库的简单操作,所以写下这篇文章,总结一下学习到的知识.浅陋之处,多多见谅. 补充一下:一直弄不清SQL Server,Mysql ,以及Or ...
- 关于 linux ssh 的配置.
一.禁止root用户远程登录: # cd /etc/ssh # vi sshd_config 将 permitRootLogin 后面的值改成 no 如下图: 然后再重启sshd服务即可,如下: # ...
- ToggleButton --------- 按钮实现开关效果
ToggleButton(开关按钮)是Android系统中比较简单的一个组件,是一个具有选中和未选择状态双状态的按钮,并且需要为不同的状态设置不同的显示文本 ,默认状态下 关. ToggleButto ...
- EasyuiCombobox三级联动
有许多刚接触Easyui中Combobox控件的朋友可能都会遇到的问题:如何将Combobox做成三级联动? 先本人有个三级联动的案例给大家参考参考,经测试能通过.注意Combobox绑定的数据是Js ...
- iBatis2之SqlMap配置总结(18条)
iBatis2之SqlMap配置总结(18条) SqlMap的配置是iBatis中应用的核心.这部分任务占据了iBatis开发的70的工作量. 1.命名空间: <sqlMap names ...