python笔记-面向对象

2018-06-26 88次浏览 发表评论

面向对象技术简介

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。定义类名首字母必须大写(双驼峰)
  • 方法:类中定义的函数。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 实例变量:定义在方法中的变量,只作用于当前实例的类。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
  • 实例化:创建一个类的实例,类的具体对象。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

定义一个类示例:

  • class 类(人)
  • instance 实例 (你、我、他)
  • 你会有些属性(身高、年龄、体重) --类属性 Property
  • 你会有些技能(吃饭、泡妞)           --方    法 Method

__init__()方法的主要作用,就是初始化你的属性(Property),这些属性在上帝初始化你的时候就要赋予给你。

比如zhangsan = Person(170,29,50)这时上帝就把你创造出来了,也就是实例化了你,然后,你到底有哪些技能(方法 Method)呢,这就看有没有在类里面定义了,如果有定义泡妞的技能,那么你就可以调用泡妞的技能(方法)来泡妞。

class Person(object):

    # 这里就是初始化你将要创建的实例的属性
    def __init__(self, hight, weight, age):
        self.hight = hight
        self.weight = weight
        self.age = age

    # 定义你将要创建的实例所有用的技能(方法)
    def paoniu(self):
        print('你拥有泡妞的技能')

    def eat(self):
        print('you can eat')

# 实例化类
zhangsan = Person(170, 50, 29)
lisi = Person(175, 100, 30)

# 访问类的属性和方法
zhangsan.paoniu()
lisi.eat()

self代表类的实例,而非类,类的方法与普通的函数只有一个特别的区别:它们必须有一个额外的第一个参数名称, 按照惯例它的名称是self

访问限制

如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问。

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))

改完后,对于外部代码来说,没什么变动,但是已经无法从外部访问实例变量.__name和实例变量.__score了。

如果外部代码要获取namescore,可以给Student类定义get_name()get_score()这样的方法:

class Student(object):
    ...

    def get_name(self):
        return self.__name

    def get_score(self):
        return self.__score

如果要允许外部代码修改score,可以再给Student类增加set_score()方法:

class Student(object):
    ...

    def set_score(self, score):
        self.__score = score
  • 在Python中,变量名类似__xxx__的是特殊变量,可以被直接访问,所以不能定义类似这样的变量作为private变量。
  •  一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是按照约定不能访问。

继承

在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类(Base class、Super class)。

我们已经编写了一个名为Animal的class,有一个run()方法可以直接打印:

class Animal(object):
    def run(self):
        print('Animal is running...')

当我们需要编写DogCat类时,就可以直接从Animal类继承:

class Dog(Animal):
    pass

class Cat(Animal):
    pass

对于Dog来说,Animal就是它的父类,对于Animal来说,Dog就是它的子类。子类也可以定义自己的方法覆盖父类。

获取对象信息

使用isinstance()

如果定义一个类,继承关系是:

object -> Animal -> Dog -> Husky

a = Animal()
d = Dog()
h = Husky()

isinstance(h, Husky)    # => True  因为h变量指向的就是Husky对象。
isinstance(h, Dog)      # => True  因为Husky继承Dog所以为真。
isinstance(d, Husky)    # => False 

能用type()判断的基本类型也可以用isinstance()判断:

print(isinstance('a', str))                   # => True
print(isinstance(123, int))                   # => True
print(isinstance(b'a', bytes))                # => True
print(isinstance([1, 2, 3], (list, tuple)))   # => True
print(isinstance((1, 2, 3), (list, tuple)))   # => True

优先使用isinstance()判断对象类型,因为它可以包揽全部对象。

获得一个对象的所有属性和方法

可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

print(dir('ABC'))
['__add__', '__class__', '__contains__', '__delattr__', ... ... 'upper', 'zfill']

定义一个类:

class MyObject(object):

    def __init__(self):
        self.x = 9

    def power(self):
        return self.x * self.x

a = MyObject()

查看这个类的属性和方法:

print(dir(a))
['__class__', '__delattr__', '__dict__', '__dir__', ... ... '__weakref__', 'power', 'x']

配合getattr()setattr()以及hasattr(),我们可以直接操作一个对象的状态:

print(hasattr(a, 'x'))       # => True 判断是否有属性'x'
print(a.x)                   # => 9
print(hasattr(a, 'y'))       # => False 判断是否有属性'y'
setattr(a, 'y', 19)          # 设置一个属性'y'
print(hasattr(a, 'y'))       # => True 判断是否有属性'y'
print(getattr(a, 'y'))       # => 19 获取属性'y'
print(a.y)                   # => 19 获取属性'y'
print(getattr(a, 'z'))       # => 如果不存在抛出 AttributeError 错误
print(getattr(a, 'z', 404))  # => 获取属性'z',如果不存在,返回默认值404
print(hasattr(a, 'power'))   # => True 判断是否有对象'power'
fn = getattr(a, 'power')     # => 获取属性'power'并赋值到变量fn
print(fn())                  # => 81 调用fn()与调用a.power()是一样的

以上的操作方法只有在不知道对象信息的时候才这样做,如果已经知道对象内部信息就不要这样做。

为了统计学生人数,可以给Student类增加一个类属性,每创建一个实例,该属性自动增加:

class Student(object):
    count = 0
    def __init__(self, name):
        self.name = name
        Student.count += 1

a = Student('aaa')
b = Student('bbb')
c = Student('ccc')

print(Student.count)    # => 3

评论

随便说点,聊聊天~