Python-Class

这篇博客学习python的面向对象,博主的目的是学习其语法。

0. 前言:#

  • python是动态语言,允许对对象绑定任何数据。
  • python有一个私有变量的仿制品,但可以通过不同版本的解释器的特性对“私有”进行破解

1. 类的基本操作:#

感受一下这些操作

1
2
3
4
5
6
7
8
9
10
class Student(object):
pass # 定义类

Hebown=Student() # 创建对象
Hebown.name='Hebown' # 绑定属性,这个属性不一定非得存在于模板中
# 绑定函数,python,很神奇吧。
# 给实例绑定的函数只能适用于这个实例,想要对这个类都适用的话,需要绑定到类上。
Hebown.age=12

print("I'm %s, and I'm %d years old."%(Hebown.name,Hebown.age))

或者提前约定必须给定的属性。

1
2
3
4
5
6
7
8
9
10
class Student(object):
name='Student' # 类属性,优先级小于实例属性,可以作为下位替代实例属性的name.
count=0 # 类似于
def __init__(self,name,age):
self.name=name
self.age=age # self 表示创建的实例本身。
# 方法可以获取内部的成员/属性。外部是不行的

Hebown=Student('Hebown',12) # 创建的时候不需要self,解释器会自己传这个变量。
# 每个成员函数都会自动传这个变量,也正因为如此,创建函数的时候必须给出这个变量,不管你用到没有,否则解释器会报错。而且如果你的函数用不到内部的成员,就不应该放到这个类的定义中。

封装:#

在属性名称前加上两个下划线,就变成了一个私有变量。否则外部可以直接进行修改。

提供get方法来帮助外界获取属性值,set方法来进行输入。

名称前后有两个双下划线的变量是特殊变量,可以直接访问。

1
2
3
4
5
6
7
8
9
10
11
class Student(object):
def __init__(self,name,age):
self.__name=name
self.__age=age
def get_score(self):
return self.name
def set_score(self,score):
if(0<=score<=100):
self.__score=score # 为模板设计者提供更多设计空间和权力
else:
raise ValueError('Invalid Input!')

简单来说,不完全封装。

继承和多态:#

python允许继承和多态。

python的多态非常宽泛,只要调用时具有相应的方法即可。

继承直接获得父类的全部内容,并且允许对父类的相同名称方法进行重写,代码运行的时候总是会调用子类的重写方法。

object可以省略。

一些别的用法:#

  1. 使用__slots__规定其实例属性的范围,限制可以添加的属性。但限制不了子类。除非在子类中也使用__slots__
    1
    2
    class Student(object):
    __slots__=('name','age') # 使用tuple定义允许绑定的属性名称
  2. 提供了get/set方法后,使用方法来获取值略显复杂,这时可以使用装饰器(decorator)将这个方法转化为属性调用的方式,更加平易近人。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    class Student(object):

    def __init__(self,name,age):
    self.name=name
    self.age=age
    @property
    def age(self):
    return self.__age

    @age.setter
    def age(self,value):
    pass # 这里定义具体的set方法的约束内容。

    Hebown=Student()
    Hebown.age=1000 # 这里也许会超出所做的限制。

如果只定义了getter方法那么就只是一个只读属性,类似于readonly

  1. 多重继承:
    python中所用继承更多的是作为一种接口?相当于为我即将要设计的内容进行分割,有的可以使用已经存在的内容进行顶替。
    这种类一般作为MIxIn类存在,专门添加相应的功能。
    比如这个例子:
    Python自带的很多库也使用了MixIn。举个例子,Python自带了TCPServer和UDPServer这两类网络服务,而要同时服务多个用户就必须使用多进程或多线程模型,这两种模型由ForkingMixIn和ThreadingMixIn提供。通过组合,我们就可以创造出合适的服务来。比如,编写一个多进程模式的TCP服务,定义如下:

    1
    2
    class MyTCPServer(TCPServer, ForkingMixIn):
    pass

    编写一个多线程模式的UDP服务,定义如下:

    1
    2
    class MyUDPServer(UDPServer, ThreadingMixIn):
    pass
  2. 其他内容:
    参见下面的链接,是一些修饰。

    • 定制类,其中比较关键的是__getitem__方法,类似于索引器;__getattr__方法可以实现动态调用资源内容。
    • 枚举类,使用如下:
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      from enum import Enum

      Month=Enum('Month',('Jan','Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
      # 这里创建了一个枚举类型Month

      # 访问其成员:
      for name, member in Month.__members__.items():
      print(name, '=>', member, ',', member.value)# 形式类似元组。value默认是相同名称,除非赋值。
      # 或者从Enum派生出自定义类:
      from enum import unique

      @unique # 检查是否有重复值
      class Weekday(Enum):
      Sun = 0 # Sun的value被设定为0
      Mon = 1
      Tue = 2
      Wed = 3
      Thu = 4
      Fri = 5
      Sat = 6
    1. 元类:这个比较关键。动态语言和静态语言最大的不同,就是函数和类的定义不是编译时定义的,而是运行时动态创建的。这个创建是通过type函数创建的。例如
      1
      2
      3
      def fn(self,name='world'):
      print("Hello, %s"%name)
      Hello=type('Hello',(object,), dict(hello=fn)) #
      还可以使用元类,就是类的类,其从type派生而来,是为类的模板。创建数据库可以用到这个,因为每一条数据都有可能不一样,这样创建类而非绑定对象非常合适。
      不过我没学明白。