Java程序员学python3.0--面向对象篇

参考廖雪峰大神的python3.0教程,适用于有一定基础的Java程序员,会对比着Java来学习python。代码在PyCharm中运行通过,地址为github。本篇主要介绍python面向对象编程相关的知识,在上一篇介绍了python的一些基础知识,包括安装运行、基础语法、函数、高级特性、函数式编程、模块等。

面向对象编程

类和对象

  • 定义类语法:class ClassName(superClass/object),其中括号里为父类,没有的话写object
  • 类中定义的函数第一个参数永远是实例变量self,调用时,不用传递该参数。
  • 允许对实例动态增加变量和方法,类的不同实例拥有的变量和方法可能不同
  • 允许对类动态添加方法,添加后对象都能访问
  • 类动态添加属性限制slots:定义一个特殊的slots变量,来限制该class实例能动态添加的属性。仅对当前类实例起作用,子类不起作用


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from types import MethodType
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
def print_score(self):
print('%s: %s' % (self.name, self.score))
# 对象动态添加属性
bart = Student('Bart Simpson', 59)
bart.age = 8
bart.print_score()
print(bart.age)
# 对象动态添加方法
def set_age(self, age):
self.age = age
lisa = Student('Lisa Simpson', 87)
lisa.set_age = MethodType(set_age, lisa)
lisa.set_age(8)
print(lisa.age)
# 给类动态添加方法
def set_score(self, score):
self.score = score
Student.set_score = set_score
lisa.set_score(10)
bart.set_score(10)
print(lisa.score)

访问限制

私有变量(private):两个下划线开头xxx,跟java一样可以有set和get方法。区别于两个下划线开头和结尾的特殊变量xxx__

1
2
3
4
5
6
7
8
class Student(object):
def __init__(self, name, score):
self.__name = name
self.__score = score
def print_score(self):
print('%s: %s' % (self.__name, self.__score))
bart = Student('Bart Simpson', 98)
bart.print_score()

继承和多态

  • 与java相同点:继承父类的所有功能,支持方法覆盖
  • 与java不同点:
    • Python动态语言–Java静态语言。下例:只需要保证传入的对象有一个run()方法就可以了,不需要是Animal类
    • Python支持多重继承,可以同时继承多个类。而Java的继承extends只能去继承一个类
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      # 父类-动物
      class Animal(object):
      def run(self):
      print('Animal is running...')
      # 父类-尖叫
      class MixlnBark(object):
      def bark(self):
      print("Barking....");
      # 方法:依赖于run方法
      def run_twice(animal):
      animal.run()
      animal.run()
      # 多重继承示例
      class Dog(Animal,MixlnBark):
      def run(self):
      print("Dog is Running");
      dog = Dog();
      dog.run()
      dog.bark()
      # 动态语言示例
      class Timer(object):
      def run(self):
      print('Start...')
      run_twice(Dog())
      run_twice(Timer())

获取对象信息

  • type(对象):获取类型
  • isinstance(判断的实例,类型1,类型2…):判断实例是否是这几种类型
  • dir(对象):获取对象所有属性和方法。配合以下方法,直接操作一个对象的状态,通常先通过has判断对象有没有该方法,有的话执行:
    • hasattr(对象,’属性名/方法名’)
    • getattr(对象,’属性名/方法名’)
    • setattr(对象,’属性名/方法名’,set值)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      import types
      # type
      print(type(abs)==types.BuiltinFunctionType)
      # isinstance
      print(isinstance('a', str))
      print(isinstance([1, 2, 3], (list, tuple)))
      # dir
      print(dir('abc'))
      print(hasattr('abc', '__init__'))

类属性和实例属性

类属性就类似于java中的类的静态属性,static

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 学生
class Student(object):
# 用于记录已经注册学生数
student_number = 0
def __init__(self, name):
self.name = name
# 注册一个学生:注册必填项名字,选填项利用关键字参数传递。注册完成,学生数+1
def register(name, **kw):
a = Student(name)
for k, v in kw.items():
setattr(a, k, v)
Student.student_number += 1
return a
bob = register('Bob', score=90)
ah = register('Ah', age=8)
print(getattr(bob, 'score'))
print(getattr(ah, 'age'))
print(Student.student_number)

面向对象高级编程

检查参数与@property

定制类

xxx前后两个下划线的函数帮助定制类,重写这些方法之后,可以实现一些功能。

  • str:类似于java的toString()
  • getattr:获取属性,可以用于防止没有此属性,也可以用于链式调用
  • call:相当于直接运行一个对象,不需要方法,这个方法相当于默认方法。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    class Student(object):
    def __init__(self, name):
    self.name = name
    def __str__(self):
    return 'Student object (name: %s)' % self.name
    def __getattr__(self, attr):
    if attr == 'score':
    return 99
    elif attr == 'age':
    return lambda: 25
    else:
    raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
    def __call__(self):
    print('My name is %s.' % self.name)
    stu = Student('Michael')
    print(stu)
    print(stu.score)
    print(stu.age)
    # print(stu.phone)
    print(stu())
    callable(stu)
    # __getattr__应用:链式调用
    class Chain(object):
    def __init__(self, path=''):
    self._path = path
    def __getattr__(self, path):
    return Chain('%s/%s' % (self._path, path))
    def __str__(self):
    return self._path
    print(Chain().status.user.timeline.list)
  • iter
    如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个iter()方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环

  • getitem
    要表现得像list那样按照下标取出元素,需要实现getitem()方法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    # __iter__和__next__:将斐波那契数列改成可以for循环的形式
    # __getitem__:使其实现取元素的功能
    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 > 100: # 退出循环的条件
    raise StopIteration();
    return self.a # 返回下一个值
    def __getitem__(self, n):
    if isinstance(n, int): # n是索引
    a, b = 1, 1
    for x in range(n):
    a, b = b, a + b
    return a
    if isinstance(n, slice): # n是切片
    start = n.start
    stop = n.stop
    if start is None:
    start = 0
    a, b = 1, 1
    L = []
    for x in range(stop):
    if x >= start:
    L.append(a)
    a, b = b, a + b
    return L
    for n in Fib():
    print(n)
    f = Fib()
    print(f[3])
    print(f[:5])

枚举类

Enum可以把一组相关常量定义在一个class中,且class不可变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@unique
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
day1 = Weekday.Mon
print(Weekday.Tue)
print(Weekday['Tue'])
print(Weekday.Tue.value)
print(day1 == Weekday.Tue)
print(Weekday(1))
print(day1 == Weekday(1))

元类

参考

http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
http://blog.csdn.net/pipisorry/article/details/39909057

文章目录
  1. 1. 面向对象编程
    1. 1.1. 类和对象
    2. 1.2. 访问限制
    3. 1.3. 继承和多态
    4. 1.4. 获取对象信息
    5. 1.5. 类属性和实例属性
  2. 2. 面向对象高级编程
    1. 2.1. 检查参数与@property
    2. 2.2. 定制类
    3. 2.3. 枚举类
    4. 2.4. 元类
  3. 3. 参考
|