您的位置:首页 > 编程语言 > Python开发

Python 面向对象基础

2020-02-01 13:46 447 查看

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

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

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

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

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

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

  ·class 是关键字

  ·创建对象后面要加括号

面向对象举例

1 class add:
2
3     def foo(self, a, b):
4         print("%s" % (a + b))
5         return 222222
6
7 obj = add()
8 c = obj.foo(1, 2)
9 print(c)
10
11 class Bar:
12
13     def foo(self, arg):
14         print(self, self.name, self.age, self.gender, arg)
15
16 z = Bar()
17 z.name = "alex"
18 z.age = 84
19 z.gender = "zhong"
20 z.foo(666)
21
22 z1 = Bar()
23 z1.name = "eric"
24 z1.age = 73
25 z1.gender = "nv"
26 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 子类(父类):

1 class F:
2     def f1(self, b):
3         print("F.f1", b)
4
5     def f2(self):
6         print("F.f2")
7
8
9 class S(F):
10
11     def s1(self):
12         print("S.s1")
13
14
15     def f2(self):
16         super(S, self).f2()
17         print("S.f2")
18         F.f2(self)
19
20 obj = S()
21
22 obj.s1()
23 obj.f1(2)
24 obj.f2()

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

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

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

如图,E继承D,C

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

 

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

1 class BaseRequest:
2     pass
3
4
5 class RequestHandler(BaseRequest):
6
7     def sever_forever(self):
8
9         print("RequestHandler.sever_forever")
10         self.process_request()     # 重新回到Son里寻找,最后运行Minx里的procexx_request()
11
12     def process_request(self):
13         print("RequestHandler.process_request")
14
15
16 class Minx:
17
18     def process_request(self):
19         print("minx.process_request")
20
21
22 class Son(Minx, RequestHandler):
23     pass
24
25 obj = Son()
26 obj.sever_forever()
27

 

多态

自带多态

 

进阶

 类的成员

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

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

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

  ·普通字段属于对象

  ·静态字段属于类

1 class Province:
2
3     # 静态字段,保存在类中
4     country = '中国'
5
6     def __init__(self, name):
7
8         # 普通字段,保存在对象中
9         self.name = name
10
11
12 # 直接访问普通字段  , 通过对象访问
13 obj = Province('河北省')
14 print(obj.name)
15
16 # 直接访问静态字段 ,通过类访问, 也可通过对象访问
17 Province.country
18
19 字段的定义和使用

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

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

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

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

方法

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

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

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

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

1 class Foo:
2
3     def __init__(self, name):
4         self.name = name
5
6     def ord_func(self):
7         """ 定义普通方法,至少有一个self参数 """
8
9         # print self.name
10         print('普通方法')
11
12     @classmethod
13     def class_func(cls):
14         """ 定义类方法,至少有一个cls参数 
cls是类名,保存在类中
       """ 15 16 print('类方法') 17 18 @staticmethod 19 def static_func(): 20 """ 定义静态方法 ,无默认参数""" 21 22 print('静态方法') 23 24 25 # 调用普通方法 26 f = Foo() 27 f.ord_func() 28 29 # 调用类方法 30 Foo.class_func() 31 32 # 调用静态方法 33 Foo.static_func() 34 35 方法的定义和使用

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

属性

 属性是普通方法的变种。

1.属性的基本使用

1 # ############### 定义 ###############
2 class Foo:
3
4     def func(self):
5         pass
6
7     # 定义属性
8     @property
9     def prop(self):
10         pass
11 # ############### 调用 ###############
12 foo_obj = Foo()
13
14 foo_obj.func()
15 foo_obj.prop   #调用属性
16
17 属性的定义和使用

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

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

调用时,无需括号

  方法: foo_obj.fun()

  属性: foo_obj.prop

1 class Pergination:
2     def __init__(self, current_page):
3         try:
4             p1 = int(current_page)
5         except Exception as e:
6             p1 = 1
7
8         self.page = p1
9
10     @property
11     def start(self):
12         val = (self.page - 1) * 10
13         return val
14
15     @property
16     def end(self):
17         val2 = self.page * 10
18         return val2
19
20
21 li = []
22 for i in range(1000):
23     li.append(i)
24
25
26 while True:
27     p = input("请输入要查看的页码:")
28     obj = Pergination(p)
29     print(li[obj.start: obj.end])

2.属性的两种定义方式

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

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

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

1 class Goods(object):
2
3     def __init__(self):
4         # 原价
5         self.original_price = 100
6         # 折扣
7         self.discount = 0.8
8
9     @property
10     def price(self):
11         # 实际价格 = 原价 * 折扣
12         new_price = self.original_price * self.discount
13         return new_price
14
15     @price.setter
16     def price(self, value):
17         self.original_price = value
18
19     @price.deltter
20     def price(self, value):
21         del self.original_price
22
23 obj = Goods()
24 obj.price         # 获取商品价格
25 obj.price = 200   # 修改商品原价
26 del obj.price     # 删除商品原价   # 与删除操作无关,只对应@price.deltter
27

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

1 class Foo:
2
3     def get_bar(self):
4         return 'wupeiqi'
5
6     BAR = property(get_bar)
7
8 obj = Foo()
9 reuslt = obj.BAR        # 自动调用get_bar方法,并获取方法的返回值
10 print(reuslt)

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

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

 成员修饰符

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

1 class Foo:
2
3     def __init__(self, name, age):
4         self.name = name
5         # self.age = age
6         self.__age = age   # 私有,外部无法直接访问
7
8     def show(self):
9         return self.__age
10
11
12 obj = Foo('alex', 19)
13 print(obj.name)
14 # obj.age
15 # print(obj.__age)
16 ret = obj.show()
17 print(ret)
View Code
1 class Foo:
2     __v = '123'
3
4     def __init__(self):
5         pass
6     def show(self):
7         return Foo.__v
8     @staticmethod
9     def stat():
10         return Foo.__v
11 # print(Foo.__v)
12 # ret = Foo().show()
13 # print(ret)
14
15 ret = Foo.stat()
16 print(ret)
View Code2
1 class Foo:
2     def __f1(self):
3         return 123
4
5     def f2(self):
6         r = self.__f1()
7         return r
8
9 obj = Foo()
10 ret = obj.f2()
11 print(ret)
View Code3

 类的特殊成员

1.__init__

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

2.__del__

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

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

class Foo:

def __del__(self):
pass
__del__

3.__call__

对象后面加括号触发执行

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

1 class Foo:
2
3     def __init__(self):
4         pass
5
6     def __call__(self, *args, **kwargs):
7
8         print '__call__'
9
10
11 obj = Foo() # 执行 __init__
12 obj()       # 执行 __call__
__call__

 

1 class Entity:
2
3     def __init__(self, size, x, y):
4         self.size = size
5         self.x = x
6         self.y = y
7         print(self.x, self.y)
8
9     def __call__(self, x, y):
10         self.x, self.y = x, y
11 obj = Entity(6, 8, 9)
12
13 obj(10, 19)
14 print(obj.x, obj.y)
15 # 10 19
16 # x和y的值改变了
应用

 

4.__int__、__str__

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

1 class Foo:
2
3     def __init__(self,n,a):
4         self.name =n
5         self.age =a
6
7     def __str__(self):
8         return '%s-%s' %(self.name,self.age,)
9
10 obj = Foo('alex', 18)
11 print(obj) #print(str(obj)) str(obj)   obj中__str__,并获取其返回值
__str__

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

1 class Foo:
2
3     def __init__(self):
4         pass
5
6     def __int__(self):
7         return 1111
8
9     def __str__(self):
10         return 'alex'
11
12 obj = Foo()
13 print(obj, type(obj))
14
15 # int,对象,自动执行对象的 __int__方法,并将返回值赋值给int对象
16 r = int(obj)
17 print(r)
18 i = str(obj)
19 print(i)
20 """
21 输出为
22 alex <class '__main__.Foo'>
23 1111
24 alex
25 """
__int__

5.__add__

两个对象相加时,自动执行第一个对象的的 __add__方法,并且将第二个对象当作参数传递进入
1 class Foo:
2
3     def __init__(self, name, age):
4         self.name = name
5         self.age = age
6
7     def __add__(self, other):
8         # self = obj1 (alex,19)
9         # other = obj2(eric,66)
10         # return self.age + other.age
11         #return Foo('tt',99)
12         return Foo(self.name, other.age)
13
14     # def __del__(self):
15     #     print('析构方法')  # 对象被销毁()时,自动执行
16
17 obj1 = Foo('alex', 19)
18 obj2 = Foo('eirc', 66)
19
20 r = obj1 + obj2
21 # 两个对象相加时,自动执行第一个对象的的 __add__方法,并且将第二个对象当作参数传递进入
22 print(r, type(r))
23 print(r.name, r.age)
24 '''
25 输出为
26 <__main__.Foo object at 0x000001F81BD29390> <class '__main__.Foo'>
27 alex 66
28 '''
__add__

6.__dict__

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

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

1 class Province:
2
3     country = 'China'
4
5     def __init__(self, name, count):
6         self.name = name
7         self.count = count
8
9     def func(self, *args, **kwargs):
10         print('func')
11
12 # 获取类的成员,即:静态字段、方法、
13 print(Province.__dict__)
14 # 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
15
16 obj1 = Province('HeBei',10000)
17 print(obj1.__dict__)
18 # 获取 对象obj1 的成员
19 # 输出:{'count': 10000, 'name': 'HeBei'}
20
21 obj2 = Province('HeNan', 3888)
22 print(obj2.__dict__)
23 # 获取 对象obj1 的成员
24 # 输出:{'count': 3888, 'name': 'HeNan'}
__dict__

7.__getitem__、__setitem__、__delitem__

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

1 class Foo(object):
2     def __getitem__(self, key):
3         print('__getitem__', key)
4
5
6     def __setitem__(self, key, value):
7         print('__setitem__', key, value)
8
9
10     def __delitem__(self, key):
11         print('__delitem__', key)
12
13
14 obj = Foo()
15
16 result = obj[0]  # 自动触发执行 __getitem__
17 obj[1] = 'wupeiqi'  # 自动触发执行 __setitem__
18 del obj[2]  # 自动触发执行 __delitem__
View Code
1 class Foo:
2
3     def __init__(self, name,age):
4         self.name = name
5         self.age = age
6
7     def __getitem__(self, item):
8         # return item+10
9         # 如果item是基本类型:int,str,索引获取
10         # slice对象的话,切片
11         if type(item) == slice:
12             print('调用这希望内部做切片处理')
13         else:
14             print(item.start)
15             print(item.stop)
16             print(item.step)
17             print('调用这希望内部做索引处理')
18
19     def __setitem__(self, key, value):
20         print(key, value)
21
22     def __delitem__(self, key):
23         print(key)
24
25 li = Foo('alex', 18)
26 # li[123]
27 li[1:4:2]
28
29 li[1:3] = [11, 22]
30
31 del li[1: 3]
32 '''
33 输出为
34 调用这希望内部做切片处理
35 slice(1, 3, None) [11, 22]
36 slice(1, 3, None)
37 '''
View Code2

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的构造函数

1 def func(self):
2     print('hello wupeiqi')
3
4
5
6 Foo = type('Foo', (object,), {'func': func})
7 # type第一个参数:类名
8 # type第二个参数:当前类的基类
9 # type第三个参数:类的成员
10 a = Foo()
11 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要加引号

1 >>> class test():
2 ...     name="xiaohua"
3 ...     def run(self):
4 ...             return "HelloWord"
5 ...
6 >>> t=test()
7 >>> hasattr(t, "name") #判断对象有name属性
8 True
9 >>> hasattr(t, "run")  #判断对象有run方法
10 True
11 >>>

getattr(object, name[, default])

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

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

setattr(object, name, values)

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

1 >>> class test():
2 ...     name="xiaohua"
3 ...     def run(self):
4 ...             return "HelloWord"
5 ...
6 >>> t=test()
7 >>> hasattr(t, "age")   #判断属性是否存在
8 False
9 >>> setattr(t, "age", "18")   #为属相赋值,并没有返回值
10 >>> hasattr(t, "age")    #属性存在了
11 True
12 >>>

delattr(object, name)

删除对象的属性

综合应用

1 >>> class test():
2 ...     name="xiaohua"
3 ...     def run(self):
4 ...             return "HelloWord"
5 ...
6 >>> t=test()
7 >>> getattr(t, "age")    #age属性不存在
8 Traceback (most recent call last):
9   File "<stdin>", line 1, in <module>
10 AttributeError: test instance has no attribute 'age'
11 >>> getattr(t, "age", setattr(t, "age", "18")) #age属性不存在时,设置该属性
12 '18'
13 >>> getattr(t, "age")  #可检测设置成功
14 '18'
15 >>>

 

转载于:https://www.cnblogs.com/bw13/p/5893691.html

  • 点赞
  • 收藏
  • 分享
  • 文章举报
dengdieli5313 发布了0 篇原创文章 · 获赞 0 · 访问量 119 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: