python之面向对象编程基础

来源:互联网 发布:vpn free mac 编辑:程序博客网 时间:2024/04/29 15:34

面向对象编程是一种编程范式,在面向对象编程中有一个很重要的概念就是类。
什么是类呢?类是一个抽象的概念,它是一类具有共同特征的具体对象的抽象描述。比如在一个学校有张三,李四,王五等学生,他们都是具体的一个个对象(也称作实例),把他们抽象成一个概念就是学生这个类。

1.类对象

由于在python中一切皆对象,所以我会把类称为类对象,实例称为实例对象。类对象创建的代码如下:

class MyClass:    i = 12345    def func(self):        return 'hello world'

这样就创建好了类对象,class与def声明不同的地方是,第一次代码运行到class会继续执行里面的代码,因为以后实例的创建会依赖类对象。
类对象支持的两种操作是属性引用和实例化。
(1)属性引用:
数据属性(以后称为属性),Myclass.i称为数据属性。
方法属性(以后称为方法),Myclass.func称为方法属性,方法的使用方式和属性的使用方式不同,需要加括号调用。
(2)实例化:
依据类对象创建实例,例如:s = Myclass(),这样就创建了一个实例s。

2.实例对象

类对象经过实例化以后就生成了一个实例,例如:

class MyClass:    i = 12345    def __init__(self,name):    #初始化实例的数据属性值        self.name = name    def func(self):        return 'hello world's = Myclass("i am s")

实例对象支持一种操作,属性引用,但是是属性引用分为数据属性和方法属性。
(1)数据属性:
s.name就称为实例的数据属性。
(2)方法属性:
s.func就称为实例方法属性(但是不存在与实例对象中,只存在于类对象中),实例对象只保存自己的数据属性。

3.方法对象

方法对象这个概念其实是为了解释在调用方法时python解释器做的一些工作。
在调用不管是类的方法(以上还没有写属于类的方法),实例的方法时,本质都是在调用类对象里面封装的函数。只是在调用的时候,例如:s.func(),解释器里面是执行Myclass.func(s)这个操作,表示调用Myclass类里面的func函数,把s作为参数传入,当然你也可以传入多个其它参数。好,接下来python解释器就把上面的调用函数的操作封装成一个对象,这个对象就是方法对象s.func。
综上的描述,我们理顺在调用方法时(如s.func())的执行流程:首先,会判断实例对象的类对象里面是否有func函数,如果有那么解释器会把s这个实例对象的数据属性和这个func函数封装进一个抽象对象即方法对象s.func,当s.func()调用这个方法对象时将自己作为第一个参数和其它参数一起传入到func这个函数,最后执行函数的功能(也就是操作实例对象的数据属性)。

4.关于类和实例的特性验证

操作类和实例就是为了操作它们的数据属性,我们可以通过内里面定义的函数去操作,也可以从外部用函数去操作,例如:

#从外部操作class Student(object):    count = 0    def __init__(self, name):        self.name = namewilber = Student("Wilber")def foo(self):#定义从外部操作实例的函数    print(self.name)foo(wilber)#从外部操作实例对象的数据属性def foo(cls):#定义从外部操作类的函数    print(cls.count)foo(Student)#从外部操作类对象的数据属性#从内部操作class Student(object):    def __init__(self, name):        self.name = name    def foo(self):        print(self.name)wilber = Student("Wilber")wilber.foo()#从内部操作实例对象的数据属性,相当于Student.foo(wilber),这里没有封装操作类的函数

5.数据属性

数据属性对于类和实例来说无非就两种情况:公有数据、私有数据。(相对于类内部和类外部)
(1)对于类对象的数据属性创建和使用如下

#类数据属性的创建class Student(object):    name = "age"                #类的公有数据属性创建    __age = 18                  #类的私有数据属性创建    def foo(self):             #通过实例对象操作类的数据属性的函数        print(Student.name)        print(Student.__age)    @classmethod    def bar(cls):              #通过类对象操作类的数据属性的函数(还可以其它类的方法)        print(cls.name)        print(cls.__age)Student.count = 90             #创建类的数据属性,只能是公有的(一般不会这样创建)#内部操作Student.bar()    #通过类操作类的数据属性s = Student()s.foo()          #通过实例操作类的数据属性#结论:从内部操作类的数据属性无论是公有还是私有都可以进行,只是需要注意操作方法。#外部操作def name(cls):  #通过外部操作共有属性    print(cls.name)def age(cls):   #通过外部操作私有属性    print(cls.__age)name(Student)    #成功age(Student)     #报错#结论:从外部只能操作公有数据属性

综上所述,类对象的数据属性有公有和私有之分(相对于外部和内部),公有数据属性可以随意从外部或内部操作,私有数据属性只能从类内部自己操作。操作的方法有两类,一类是通过实例的方法来操作(注意定义的方法),二类是通过各种类的方法来操作(以后会谈到类方法)。
(2)对于实例对象数据属性的创建和操作如下

class Student(object):    pass#实例数据属性的创建s = Student()     #创建实例对象s.count = 10      #对实例对象创建属性count,这样只能创建公有数据属性(一般不会这样创建)print(s.count)#如果我们想在创建实例对象时初始化一些属性(公有和私有),我们可以这样class Student(object):    def __init__(self, name, age):   #初始化实例的数据属性值        self.name = name             #实例对象公有数据属性        self.__age = age             #实例对象私有数据属性s = Student("jack", 18)s.count = 10                         #从外部设置实例数据属性s.__count = 90                       #不是私有数据属性#实例数据属性的操作class Student(object):    def __init__(self, name, age):        self.name = name   #实例对象公有数据属性        self.__age = age   #实例对象私有数据属性    def foo(self):        print(self.name)    def bar(self):        print(self.__age)s = Student("jack", 18)#从内部操作s.foo()      #操作公有数据属性s.bar()      #操作私有数据属性#结论:从内部可以随意操作实例数据属性#从外部操作def name(self):    print(self.name)def age(self):    print(self.__age)name(s)    #操作公有数据属性,成功age(s)     #操作私有数据属性,报错#结论:从外部只能操作公有数据属性,不能操作私有数据属性

综上所述,实例对象的数据属性有公有和私有之分(相对于外部和内部),公有数据属性可以随意从外部或内部操作,私有数据属性只能从类内部自己操作。

6.方法属性

对于类对象有它自己的方法属性,对于实例对象有它自己的方法属性,我们分别来探讨。
(1)类对象方法属性
类对象的方法属性分为,类方法和静态方法。类方法可以由@classmethod装饰器创建,静态方法可以由@staticmethod装饰器创建。
代码演示如下:

class Student(object):    name = "student"    @classmethod    #类方法,用装饰器@classmethod创建    def foo(cls):   #类方法需要传入一个cls作为第一个参数        print("classmethod")        print(cls.name)    @staticmethod   #静态方法,用装饰器@staticmethod创建    def bar():        print("staticmethod")        print(Student.name)Student.foo()       #通过类对象使用类方法Student.bar()       #通过类对象使用静态方法s = Student()       s.foo()             #通过实例对象使用类方法s.bar()             #通过实例对象使用静态方法#结论:对于类对象的类方法和静态方法,类和它的实例对象都可以使用class Abc(Student):    name = "Abc"    passAbc.foo()           #操作类的类方法,自行运行查看区别Abc.bar()           #操作类的静态方法,自行运行查看区别

静态方法和类方法的区别:
从定义方式上看,静态方法使用@staticmethod装饰器创建,类方法使用@classmethod装饰器创建并且第一个参数cls表示类本身。
(2)实例对象的方法属性
实例方法属性。代码如下:

class Student(object):    def __init__(self, name):        self.name = name    def foo(self):      #实例的方法,第一个self参数表示实例自己        print(self.name)s = Student("jack")s.foo()                 #实例对象调用实例方法Student.foo()  #报错    #类对象调用实例方法#结论:实例方法只能实例对象调用,类对象不能调用

用实例方法只能s.foo()这样来调用,我们还可以用@property装饰器来将方法属性伪装成数据属性的调用方式s.foo也可以执行。但是这里只是伪装,实际还是通过方法属性来调用。
@property装饰器

class Student(object):    def __init__(self, name):        self._name = name    @property               #property装饰器,将方法的调用方式伪装成数据属性的调用方式,用于读数据    def foo(self):        "i am foo's property"   #文档字符串        return self._name    @foo.setter             #上面使用property装饰器后就生成了一个setter装饰器,用于写数据    def foo(self, new_name):        self._name = new_name    @foo.deleter    def foo(self):        del self._names = Student("jack")print(s.foo)s.foo = "vision"         #为foo属性赋值print(s.foo)del s.foo                #删除foo属性print(s.foo)             #报错#结论:上面通过s.foo()来调用,现在通过@property装饰器后可以直接s.foo来使用,可读、可写#还可以用另一种方式使用propertyclass Student(object):    def __init__(self, name):        self._name = name    @property               #property装饰器,将方法的调用方式伪装成数据属性的调用方式,用于读数据    def get_foo(self):        return self._name    @foo.setter             #上面使用property装饰器后就生成了一个setter装饰器,用于写数据    def set_foo(self, new_name):        self._name = new_name    @foo.deleter    def del_foo(self):        del self._namefoo = property(get_foo, set_foo, del_foo,"i am foo's property")s = Student("jack")#s.foo调用getter,  s.foo = value调用setter,  def s.foo调用deleter

7.公有私有说明

公有和私有是相对与类对象和实例对象的内部和外部,在数据属性或类内置的函数前面加上就表示此对象是私有,不能从外部使用只能自己内部访问。但是,其实在python中根本不存在完全私有的对象,不管是数据属性还是方法属性在前面加上都可以从外部访问,用_class__method可以使用方法,_class__shuju可以访问数据,但是强烈建议你不要这么做。私有变量除了封装数据的作用还有一个重要的使用方式就是在继承上的应用,可以防止子类覆盖父类的相同方法。例如:

class Mapping:    def __init__(self, iterable):        self.items_list = []        self.__update(iterable)    def update(self, iterable):        for item in iterable:            self.items_list.append(item)    __update = update   # 类Mapping的私有方法__update(),子类若再定义update()将不会覆盖父类的update()方法class MappingSubclass(Mapping):    def update(self, keys, values):        # 重写父类的update()方法,但是却不会修改父类的update()方法,因为父类的update()方法保存在了__update()方法        for item in zip(keys, values):            self.items_list.append(item)

还有一种情况是在数据属性、函数前面加一个_表示实现细节,将来有变化不会另行通知。

0 0
原创粉丝点击