python 对象和类

python中所有数据都是以对象形式存在。对象既包含数据(变量),也包含代码(函数),是某一类具体事物的特殊实例。

面向对象的三大特性为封装、继承和多态。

1、定义类

#定义空类
class Person():
    pass
#添加对象初始化方法
def Person():
    def __init__(self):
        pass

self参数指向正在被创建的对象本身。

self 代表的是类的实例,代表当前对象的地址,而 self.__class__ 则指向类。

#初始化方法中添加参数
def Person():
    def __init__(self,name):
        self.name=name

2、创建实例

>>>hunter=Person('Elmer Fudd')

上一行做了以下工作:

  • 查看Person类的定义
  • 在内存中实例化(创建)一个新的对象调用对象的__init__方法,将这个新创建的对象作为self传入,并将另一个参数‘Elmer Fudd’作为name传入
  • 将name的值存入对象
  • 返回这个新的对象
  • 将名字hunter和这个对象关联

3、访问属性

使用点号 . 来访问对象的属性

print(hunter.name)

一些内置类属性:

  • __dict__ : 类的属性(包含一个字典,由类的数据属性组成)
  • __doc__ :类的文档字符串
  • __name__: 类名
  • __module__: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)
  • __bases__ : 类的所有父类构成元素(包含了一个由所有父类组成的元组)

4、继承

继承即从已有类中衍生出新的类,可以添加或修改部分功能。便于代码复用。

class Car():
    pass
class Yugo(Car):
    pass

5、类方法覆盖

新创建的子类会自动继承父类的所有信息。

class Car():
    def exclaim(self):
        print("I'm a Car!")
class Yugo(Car):
    pass
t1=Car()
t2=Yugo()
>>>t1.exclaim()
I'm a Car!
>>>t2.exclaim()
I'm a Car!

对继承的方法进行修改后会覆盖原有的方法。

class Car():
    def exclaim(self):
        print("I'm a Car!")
class Yugo(Car):
    def exclaim(self):
        print("I'm a Yugo!")
t1=Car()
t2=Yugo()
>>>t1.exclaim()
I'm a Car!
>>>t2.exclaim()
I'm a Yugo!

在子类中,可以覆盖父类的方法,包括__init__()方法

class MDPerson(Person):
    def __init__(self,name):
        self.name="Doctor" + name
a=Person('Tom')
b=MDPerson('Tom')
>>>a.name
Tom
>>>b.name
Doctor Tom

6、子类添加新方法

class Car():
    def exclaim(self):
        print("I'm a Car!")
class Yugo(Car):
    def exclaim(self):
        print("I'm a Yugo!")
    def push(self):
        print('need a push')
a=Car()
b=Yugo()
>>>b.push()
need a push

7、使用super()调用父类方法

class EPerson(Person):
    def __init__(self,name,email):
        super().__init__(name)
        self.email=email

我们应当使用super()来让父类完成其应当做的事情。并且,如果父类的定义以后发生改变,使用super()可以保证这些改变会自动反映到子类上,而不需要手动修改。

8、self参数作用

以下句代码举例:

>>>t1.exclaim()
  • 查找t1对象所属的类Car
  • 把t1对象作为self参数传给Car类所包含的exclaim()方法

相当于:

>>>Car.exclaim(t1)

9、使用property属性访问

property(fget,fset,fdel,doc)

class Duck():
    def __init__(self,iname):
        self.hidden_name=iname
    def get_name(self):
        return self.hidden_name
    def set_name(self,iname):
        self.hidden_name=iname
    name=property(get_name,set_name)

最后一行将get_name,set_name定义为name属性。当访问name时,get_name()会被自动调用。当对name执行赋值操作时,set_name()方法会被调用。

tt=Duck('Howard')
>>>tt.name
'Howard'
>>>tt.name='Tom'
>>>tt.name
'Tom'

也可以通过装饰器方式定义property。

  • @property,用于指定getter方法
  • @name.setter,用于指定setter方法
class Duck():
    def __init__(self,iname):
        self.hidden_name=iname
    @property
    def name(self):
        return self.hidden_name
    @name.setter
    def name(self,iname):
        self.hidden_name=iname
    name=property(get_name,set_name)

property除指向类中存储的某一属性(如hidden_name),也可以指向计算结果值。

class Circle():
    def __init__(self,radius):
        self.radius=radius
    @property
    def diameter(self):
        return 2*self.radius
c=Circle(5)
>>>c.radius
5
>>>c.diameter
10
>>>c.radius=7
>>>c.diameter
14

如果没有指定property的setter,将无法从类的外部对它的值进行设置。

与直接访问属性相比,如果改变某一属性的定义,只需要在类定义中修改代码,不需要在每一处调用修改。

猜你喜欢

转载自www.cnblogs.com/ivan-count/p/10515702.html