python笔记--4--面向对象

面向对象
  Python中对象的概念很广泛,Python中的一切内容都可以称为对象,除了数字、字符串、列表、元组、字典、集合、range对象、zip对象等等,函数也是对象,类也是对象。
  在Python中,可以使用内置方法isinstance()来测试一个对象是否为某个类的实例。
    >>> isinstance(car, Car)
    True
    >>> isinstance(car, str)
    False
  在Python中比较特殊的是,可以动态地为类和对象增加成员,这一点是和很多面向对象程序设计语言不同的,也是Python动态类型特点的一种重要体现。

  

  私有成员

  Python并没有对私有成员提供严格的访问保护机制。
  在定义类的成员时,如果成员名以两个下划线“__”开头则表示是私有成员。在内部,python使用一种name mangling技术,将__membername替换成_classname__membername,所以你在外部使用原来的私有成员的名字时,会提示找不到。
  私有成员在类的外部不能直接访问,Python的私有成员并不是真正意义上的私有,需要通过调用对象的公有成员方法来访问,也可以通过Python支持的特殊方式来访问。

  在Python中,以下划线开头的变量名和方法名有特殊的含义,尤其是在类的定义中。用下划线作为变量名和方法名前缀和后缀来表示类的特殊成员:
    _xxx:受保护成员,不能用'from module import *'导入;
    __xxx__:系统定义的特殊成员;
    __xxx:私有成员,只有类对象自己能访问,子类对象不能直接访问到这个成员,但在对象外部可以通过“对象名._类名__xxx”这样的特殊方式来访问。

  方法

  在类中定义的方法可以粗略分为四大类:公有方法、私有方法、静态方法类方法
    公有方法、私有方法都属于对象,私有方法的名字以两个下划线“__”开始,每个对象都有自己的公有方法和私有方法,在这两类方法中可以访问属于类和对象的成员;
    公有方法通过对象名直接调用,私有方法不能通过对象名直接调用,只能在属于对象的方法中通过self调用或在外部通过Python支持的特殊方式来调用。
    如果通过类名来调用属于对象的公有方法,需要显式为该方法的self参数传递一个对象名,用来明确指定访问哪个对象的数据成员。
    静态方法和类方法都可以通过类名和对象名调用,但不能直接访问属于对象的成员,只能访问属于类的成员。
    静态方法可以没有参数。
    一般将cls作为类方法的第一个参数名称,但也可以使用其他的名字作为参数,并且在调用类方法时不需要为该参数传递值。

class Root:
    __total = 0               # 私有成员变量

    def __init__(self, v):    # 构造方法
        self.__value = v
        Root.__total += 1     # 类中成员属性属于类,需要用 类名. 来调用

    def show(self):           # 普通实例方法
        print('self.__value:', self.__value)
        print('Root.__total:', Root.__total)

    @classmethod              # 装饰器,声明类方法
    def classShowTotal(cls):  # 类方法
        print(cls.__total)

    @staticmethod             # 装饰器,声明静态方法
    def staticShowTotal():    # 静态方法
        print(Root.__total)


r = Root(3)
r.classShowTotal()              # 通过对象来调用类方法
r.staticShowTotal()             # 通过对象来调用静态方法
r.show()
rr = Root(5)
Root.classShowTotal()           # 通过类名调用类方法
Root.staticShowTotal()          # 通过类名调用静态方法
rr.show()
'''
1
1
self.__value: 3
Root.__total: 1
2
2
self.__value: 5
Root.__total: 2
'''

  @property把方法编程可调用的属性

class Student(object):
    '''测试property装饰器'''

    @property
    def birth(self):
        # 此为getter方法
        return self._birth

    @birth.setter
    def birth(self, value):
        # 此为setter方法
        self._birth = value

    @birth.deleter
    def birth(self):
        print('调用birth的deleter方法')
        del self._birth

    @property
    def age(self):
        # 没有为age设置setter方法,因此age是一个只读属性
        return 2018 - self._birth


s = Student()
s.birth = 1997          # 加上@property装饰器后,birth和age都变成属性了,age没有定义setter方法,因此为只读属性
print(s.birth)
# 1997
print(s.age)
# 21
del s.birth
# 调用birth的deleter方法

python类的特殊方法

方法

功能说明

__new__()

类的静态方法,用于确定是否要创建对象

__init__()

构造方法,创建对象时自动调用

__del__()

析构方法,释放对象时自动调用

__add__()

+

__sub__()

-

__mul__()

*

__truediv__()

/

__floordiv__()

//

__mod__()

%

__pow__()

**

__eq__()、 __ne__()、__lt__()、 __le__()、__gt__()、 __ge__()

==、 !=、<、 <=、>、 >=

__lshift__()、__rshift__()

<<、>>

__and__()、__or__()、__invert__()、__xor__()

&、|、~、^

__iadd__()、__isub__()

+=、-=,很多其他运算符也有与之对应的复合赋值运算符

__pos__()

一元运算符+,正号

__neg__()

一元运算符-,负号

__contains__ ()

与成员测试运算符in对应

__radd__()、__rsub__

反射加法、反射减法,一般与普通加法和减法具有相同的功能,但操作数的位置或顺序相反,很多其他运算符也有与之对应的反射运算符

__abs__()

与内置函数abs()对应

__bool__()

与内置函数bool()对应,要求该方法必须返回True或False

__bytes__()

与内置函数bytes()对应

__complex__()

与内置函数complex()对应,要求该方法必须返回复数

__dir__()

与内置函数dir()对应

__divmod__()

与内置函数divmod()对应

__float__()

与内置函数float()对应,要求该该方法必须返回实数

__hash__()

与内置函数hash()对应

__int__()

与内置函数int()对应,要求该方法必须返回整数

__len__()

与内置函数len()对应

__next__()

与内置函数next()对应

__reduce__()

提供对reduce()函数的支持

__reversed__()

与内置函数reversed()对应

__round__()

对内置函数round()对应

__str__()

与内置函数str()对应,要求该方法必须返回str类型的数据

__repr__()

打印、转换,要求该方法必须返回str类型的数据

__getitem__()

按照索引获取值

__setitem__()

按照索引赋值

__delattr__()

删除对象的指定属性

__getattr__()

获取对象指定属性的值,对应成员访问运算符“.”

__getattribute__()

获取对象指定属性的值,如果同时定义了该方法与__getattr__(),那么__getattr__()将不会被调用,除非在__getattribute__()中显式调用__getattr__()或者抛出AttributeError异常

__setattr__()

设置对象指定属性的值

__base__

该类的基类

__class__

返回对象所属的类

__dict__

对象所包含的属性与值的字典

__subclasses__()

返回该类的所有子类

__call__()

包含该特殊方法的类的实例可以像函数一样调用

__get__()

定义了这三个特殊方法中任何一个的类称作描述符(descriptor),描述符对象一般作为其他类的属性来使用,这三个方法分别在获取属性、修改属性值或删除属性时被调用

__set__()

__delete__()

                                                                                                                                                          

继承
  继承是为代码复用和设计复用而设计的,是面向对象程序设计的重要特性之一。设计一个新类时,如果可以继承一个已有的设计良好的类然后进行二次开发,无疑会大幅度减少开发工作量。
  在继承关系中,已有的、设计好的类称为父类或基类,新设计的类称为子类或派生类。派生类可以继承父类的公有成员,但是不能继承其私有成员。如果需要在派生类中调用基类的方法,可以使用内置函数super()或者通过“基类名.方法名()”的方式来实现这一目的。
  Python支持多继承,如果父类中有相同的方法名,而在子类中使用时没有指定父类名,则Python解释器将从左向右按顺序进行搜索。

class A(object):
    def __init__(self):
        self.__private()
        self.public()

    def __private(self):
        print('__private() method in A')

    def public(self):
        print('public() method in A')


class B(A):
    '''
    注意,类B没有定义构造函数,会调用父类A的构造函数,私有方法使用父类A的,普通公开方法使用的是自己的
    '''
    def __private(self):
        print('__private() method in B')

    def public(self):
        print('public() method in B')


class C(A):
    '''
    显式定义了构造函数,直接调用自己定义的构造函数,而不是调用父类的构造函数。
    私有方法和普通公开方法都是使用自己的。
    '''
    def __init__(self):         # 显式定义构造函数
        self.__private()
        self.public()

    def __private(self):
        print('__private() method in C')

    def public(self):
        print('public() method in C')


b = B()
c = C()
'''
__private() method in A
public() method in B
__private() method in C
public() method in C
'''

多态
  所谓多态(polymorphism),是指基类的同一个方法在不同派生类对象中具有不同的表现和行为。派生类继承了基类行为和属性之后,还会增加某些特定的行为和属性,同时还可能会对继承来的某些行为进行一定的改变,这都是多态的表现形式。
  Python大多数运算符可以作用于多种不同类型的操作数,并且对于不同类型的操作数往往有不同的表现,这本身就是多态,是通过特殊方法与运算符重载实现的。

class Animal(object):      # 定义基类
    def show(self):
        print('I am an animal.')


class Cat(Animal):         # 派生类,覆盖了基类的show()方法
    def show(self):
        print('I am a cat.')


class Dog(Animal):         # 派生类
    def show(self):
        print('I am a dog.')


class Tiger(Animal):       # 派生类
    def show(self):
        print('I am a tiger.')


class Test(Animal):        # 派生类,没有覆盖基类的show()方法
    pass


x = [item() for item in (Animal, Cat, Dog, Tiger, Test)]
for item in x:        # 遍历基类和派生类对象并调用show()方法
    item.show()
'''
I am an animal.
I am a cat.
I am a dog.
I am a tiger.
I am an animal.
'''

猜你喜欢

转载自www.cnblogs.com/chuangming/p/8996561.html
今日推荐