一、阶级关系

1. Programs are composed of modules.
2. Modules contain statements.
3. Statements contain expressions.
4. Expressions create and process objects.

 

 

二、教学大纲 

  • <Think Python>

[Python] 08 - Classes --> Objects

 

  • 菜鸟教程

Goto: http://www.runoob.com/python3/python3-class.html

参考资源:廖雪峰,Python面向对象编程

参考资源:廖雪峰,Python面向对象高级编程

参考资源:错误、调试和测试

 

  • 面向对象的三大特点

数据封装(Encapsulation )、继承(inheritance )和多态(polymorphism)。

 

 

 

 

Encapsulation


类的定义

  • 构造方法

赋值的的过程,就自动完成了类内的变量定义。

#!/usr/bin/python3
 
class Complex:
    def __init__(self, realpart, imagpart):
        self.r = realpart
        self.i = imagpart
x
= Complex(3.0, -4.5) print(x.r, x.i) # 输出结果:3.0 -4.5

 

self 参数

类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的 第一个参数名称:self

注意:self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定使用 self。

self 记录了 “类的地址”,“类的属性” 等各种类的属性。

class Test:
    def prt(self):
        print(self)        # address
        print(self.__class__)  # name
 
t = Test()
t.prt()

执行结果:

<__main__.Test instance at 0x100771878>
__main__.Test

 

 

权限控制

  • “私有” 属性 & 方法

加上 “双下划线” 定义属性为私有属性。

#!/usr/bin/python3
class people:
  name = ''
  age  = 0
  __weight = 0

def __init__(self, n, a, w):
  self.name = n
  self.age  = a
  self.__weight= w

def speak(self):
  print("weight is {}".format(self.__weight))

def __talk(self):
  print("age is {}".format(self.age))


p = people('runoob', 10, 30)


#####################
# private attribute
#####################

print(p.name)
# print(p.__weight) # <-- this is err case.
print(p._people__weight)


#####################
# private function
#####################

p.speak()
# p.__talk() # <-- this is err case.
p._people__talk()

 

“私有化” 原理

双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:

>>> bart._Student__name
'Bart Simpson'

但是强烈建议你不要这么干,因为 “不同版本的Python解释器可能会把__name改成不同的变量名”

总的来说就是,Python本身没有任何机制阻止你干坏事,一切全靠自觉。

  

  • 限制滥用 “对象成员”  

__slot__关键字

由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。

注意:使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用

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

>>> s = Student()      # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25         # 绑定属性'age'

>>> s.score = 99       # <---- 绑定属性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

 

为何用?内存环保

Ref: 10. __slots__ Magic

动态语言意味着“浪费空间”换取“灵活性”。显然,减少不必要的灵活性可以 reduce memory of RAM。添加__slots__后带来的内存环保效果如下:

The code will reduce the burden on your RAM. Some people have seen almost 40% to 50% reduction in RAM usage by using this technique. 

class MyClass(object):
    __slots__ = ['name', 'identifier']
  def __init__(self, name, identifier):
        self.name = name
        self.identifier = identifier
        self.set_up()
    # ...

 

  • 成员变量 Set & Get

过去的策略

分别定义set, get函数操作。

装饰器策略

将函数当做属性来使用:

(a) 只有@property表示只读。

(b) 同时有@property和@x.setter表示可读可写。

(c) 同时有@property和@x.setter和@x.deleter表示可读可写可删除。

 

[Python] 08 - Classes --> Objects
class student(object):
    
    def __init__(self,id):  
        self.__id=id  
        
    @property      # 只读  
    def score(self):  
        return self._score 
    
    @score.setter  # 只写  
    def score(self, value):        
        # 设置前的checker
        if not isinstance(value,int):  
            raise ValueError('score must be an integer!')    
        if value<0 or value>100:  
            raise ValueError('score must between 0 and 100')  
        # 开始设置 
        self._score=value  
               
    @property      # 只读
    def get_id(self):  
        return self.__id  

s=student('123456')  

s.score=100       #
print(s.score)     #
print(s.__dict__)
print (s.get_id)   # 只读
#s.get_id=456   #只能读,不可写: AttributeError: can't set attribute
经典方式

相关文章: