Python面向对象,面向对象高级编程

## 属性的品类
  - 属性可分为类属性和实例属性

## 使用__Python面向对象,面向对象高级编程。slots__限制类的质量
  -
之前提及,能够透过在类外部实例可能类名大肆定义实例属性可能类属性也许措施

本类别重要学习Python的中坚使用和语法知识,后续也许会围绕着AI学习进行。
Python三 (①) Python语言的简要介绍
Python三 (二) Python语法基础
Python3 (3) Python函数
Python叁 (肆) Python高等脾性
Python三(5) Python 函数式编制程序
Python3(6) Python 模块
Python三(7) Python
面向对象编制程序
Python3(8) Python 面向对象高等编制程序
Python面向对象编制程序有她协和壮大的一边,如“鸭子类型”,那是动态语言独有的性状,上1篇的面向对象基础讲了python与此外语言面向对象的共同之处,这一篇重要讲Python中故意的面向对象性子。重承继、定制类、元类等,那一篇应该算是Python学习个中的中游核心篇。

正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。

  -
实例属性能够因此在类中使用self定义,可能直接在类外部使用实例变量定义

 1 class Person(object):
 2     pass
 3 
 4 
 5 Person.name = "Stanley"         # 在外部添加类属性
 6 print(Person.name)              # 输出:Stanley
 7 
 8 per1 = Person()
 9 per1.age = 22                   # 在外部添加实例属性
10 print(per1.age)                 # 输出:22
11 
12 per2 = Person()
13 # print(per2.age)               # 实例属性只由定义该属性的实例所有,其他的实例无法访问
14 
15 
16 def outer_init(self, name):
17     self.name = name
18 
19 
20 Person.__init__ = outer_init    # 在外部修改类方法
21 per3 = Person("Lily")
22 print(per3.name)                # 输出:Lily, 说明类方法修改成功

动态的加多类的天性方法

面向对象中,对象是类的实例,集类的性质和办法于一体,由于python是动态语言,在运维时才成立类,所以python
有动态增多类属性与对象属性的力量。那一瞬间就将静态语言比下去了,如下:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from types import MethodType

class Person(object):
    def __init__(self,name):
        self._name = name

    @property
    def name(self):
        return self._name
#动态添加类的属性
Person.age = 16

p = Person("张三")
#动态添加对象的属性
p.sex = '男'
print(p.name,p.sex,p.age)

p1 = Person('李四')
print(p1.name,p.age)
#对象的属性只适用于当前对象
# print(p1.name,p1.sex,p.age)

def set_name(self,value):
    self._name = value
#动态添加对象的方法
p.set_name = MethodType(set_name,p)
p.set_name('王五')
print(p.name)

def set_age(self,value):
    self.age = value
#动态的添加类的方法
Person.set_age = set_age
p.set_age(12)
p1.set_age(13)
print(p.name,p.age)
print(p1.name,p1.age)

出口结果:

张三 男 16
李四 16
王五
王五 12
李四 13
  • 动态增添类的属性、方法,各种对象都可以用
  • 动态拉长对象的质量、方法,唯有当前指标足以用
  • 暴透露动态语言1个弱点,能够自由的丰硕方法,属性,对于从严安全性供给从严的政工明显非常,所以有3个极度的标记出现了__slots__来界定增多的品质。
class Student(object):
    pass
 1 class Person(object):
 2     def __init__(self, name, age):
 3         self.name = name
 4         self.age = age
 5 
 6 
 7 per1 = Person("Stanley", 22)
 8 print(per1.name)        # 输出:Stanley
 9 per1.weight = "50kg"    
10 print(per1.weight)      # 输出:50kg

 

__slots__ 的用法

在类中,用__slots__赋值二个tupletuple中的属性为能够增多的性质。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

class Person(object):
    __slots__ = ('name', 'age')  # 用tuple定义允许绑定的属性名称


p = Person()
p.name = "张三"
p.age = 16
p.sex = '男'

print(p.name,p.age,p.sex)

输出结果:

Traceback (most recent call last):
  File "F:/python/HelloWord/def_func.py", line 12, in <module>
    p.sex = '男'
AttributeError: 'Person' object attribute 'sex' is read-only

地点的错误消息便是不允许加多sex 属性。

  • __solts__
    在子类中,倘若采取了正是子类+父类的范围,假使未有选用父类的界定对子类没用。

class Person(object):
    __slots__ = ('name', 'age')  # 用tuple定义允许绑定的属性名称

class Child(Person):
    # __slots__ = ('weight')
    pass

c = Child()
c.name = "李四"
c.sex = "男"
print(c.name,c.sex)

出口结果:

李四 男

如果__slots__松手就能够报错,只援救name、age、weight操作。

下一场,尝试给实例绑定一脾质量:

 

  - 若想要限制实例的性质,能够采取__slots__

@property 的用法

@property的效劳正是为变量生成三个装饰器,用于把1个方法成为属性调用的。为了限制属性的赋值,化解属性赋值的随便性。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Person(object):
    @property
    def name(self):
        return self._name

    @name.setter
    def name(self,value):
        if not isinstance(value,str):
            raise ValueError('name must be an str')
        self._name= value

p = Person()
# p.name = '123'
# p.name = 123
print(p.name)

出口结果:

Traceback (most recent call last):
  File "F:/python/HelloWord/def_func.py", line 16, in <module>
    p.name = 123
  File "F:/python/HelloWord/def_func.py", line 11, in name
    raise ValueError('name must be an str')
ValueError: name must be an str

假定将整数赋值给name
会抛出大家定义的卓绝,那样就直达限制name必须str品种的效应。使我们的品质可控起来。@property用起来立马感到代码精粹多了,减低了失误的或是。

>>> s = Student()
>>> s.name = 'Michael' # 动态给实例绑定一个属性

  - 类属性则平素在类中定义
    - 类属性通过类名访问,也足以透超过实际例访问

 1 class Person(object):
 2     __slots__ = ("name", "age")     # 限制实例属性
 3     count = 1
 4 
 5 
 6 Person.nationality = "China"        # 仍然可以定义类属性
 7 print(Person.nationality)           # 输出:China
 8 
 9 
10 per1 = Person()
11 per1.name = "Lily"
12 per1.age = 17
13 
14 per1.nationality = "China"
15 # 类属性为只读属性,无法通过实例修改,只能通过类名修改
16 # AttributeError: 'Person' object attribute 'nationality' is read-only
17 
18 per1.gender = "female"
19 # 无法通过实例定义新实例属性
20 # AttributeError: 'Person' object has no attribute 'gender'
21 
22 
23 per1.count = 100
24 # AttributeError: 'Person' object attribute 'count' is read-only

多种承接

python与C++同样,援助多种继承,其实与java
中接口与承接一起用的效用差不离。Python 中称接口的筹算为 MixIn

仍是能够尝试给实例绑定一个办法:

 1 class Person(object):
 2     class_name = "Person"
 3 
 4     def __init__(self, name, age):
 5         self.name = name
 6         self.age = age
 7 
 8 
 9 per1 = Person("Stanley", 22)
10 print(per1.class_name)      # 输出:Person
11 
12 print(Person.class_name)    # 输出:Person

 

MixIn

MixIn
的宏图与接口一样,通过结合搭配来组成二个新的完整的功能,而不是学富五车承袭来达成。大家来解析一下Python
自带的TCPServer和UDPServer那两类网络服务。

#一个多进程模式的TCP服务
class MyTCPServer(TCPServer, ForkingMixIn):
    pass
#一个多线程模式的UDP服务
class MyUDPServer(UDPServer, ThreadingMixIn):
    pass
#一个协程模型
class MyTCPServer(TCPServer, CoroutineMixIn):
    pass

Python中一些功用性的类命名xxxMixIn,所以我们在书写的时候也使用这种格局,主类采取当承接的办法,一些功效性用多两次三番,作用性的类命名选择xxxMixIn的形式。

>>> def set_age(self, age): # 定义一个函数作为实例方法
...     self.age = age
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果

 

## 多种承接
  - Python是允大多种承继的,多种承袭时期子类具备多种特征

定制类

大家经过Python中放到的有的杰出标记去定制一些类

只是,给一个实例绑定的法子,对另1个实例是不起作用的:

  - 注意:
    -
借使实例属性和类属性使用了同样的名字,则实例化后实例属性将覆盖类属性,实例将无法在拜访该同名类属性,而因而类名访问类属性将不受影响

 1 class Person(object):
 2     @staticmethod
 3     def pursuit_happiness():
 4         print("幸福是奋斗出来的!")
 5 
 6 
 7 class Father(Person):
 8     character = "温和,坚韧"
 9 
10 
11 class Mather(Person):
12     interest = "阅读,文艺竞技"
13 
14 
15 class Student(Person):
16     @staticmethod
17     def do_homework():
18         print("是学生就要做作业!")
19 
20 
21 class Son(Father, Mather, Student):     # 多重继承
22     pass
23 
24 
25 s = Son()
26 # Son类实例具有了Father类的属性
27 print(s.character)              # 输出:温和,坚韧
28 # Son类实例具有了Mather类的属性
29 print(s.interest)               # 输出:阅读,文艺竞技
30 # Son类实例具有了Student类的方法
31 s.do_homework()                 # 输出:是学生就要做作业!
32 # 由于Father类,Mather类,Student类都各自继承了Person类,所以Son类也有Person类的方法
33 s.pursuit_happiness()           # 输出:幸福是奋斗出来的!

__str__ 和__repr__

__str__用以定义打字与印刷的类本人的内容,用户反映,__repr__也是打字与印刷类自己的从头到尾的经过,开辟者反馈。也等于因而命令运维时的展现。

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Person(object):
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return 'Person object (name: %s)' % self.name
    __repr__ = __str__

p = Person("张三")
print(p)

出口结果:

Person object (name: 张三)

大家演示了__str__的使用,但是__repr__亟待命令施行,所以能够团结试试。

>>> s2 = Student() # 创建新的实例
>>> s2.set_age(25) # 尝试调用方法
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'set_age'
 1 class Person(object):
 2     name = "Person"
 3 
 4     def __init__(self, name, age):
 5         self.name = name
 6         self.age = age
 7 
 8 
 9 print(Person.name)      # 输出:Person
10 
11 per1 = Person("Stanley", 22)
12 print(per1.name)        # 输出:Stanley
13 print(Person.name)      # 输出:Person

 

__iter__

__iter__
用于将类成为2个迭代目的。一般要与__next__联机利用,接下去大家定义一个可迭代的类

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己

    def __next__(self):
        self.a, self.b = self.b, self.a + self.b # 计算下一个值
        if self.a > 50: # 退出循环的条件
            raise StopIteration()
        return self.a # 返回下一个值

f = Fib()
for n in f:
    print(n)

出口结果:

1
1
2
3
5
8
13
21
34

出口的是1~50以内的斐波那契数列,那样大家定制了3个方可循环的类,与Python中放置的listtuple貌似不过还有分裂的,比如通过索引查找元素,切条技巧都以非常的,下边大家下一个标记正是创新这一个的。

为了给持有实例都绑定方法,可以给class绑定方法:

相关文章