初识面向对象编程

初识对象编程

首先我先问一个问题,我国有多少个省?

神回复:23 个
为什么是23个,而不是一个呢?
为什么每个省下有那么多个市,而不是一个呢?

那么我们分析一下:如果我们国家只有一个省,那么我们国家最大的省长就是习大大,
他下面也没有分省长,那么意味着,我们的直属领导就是习大大,我们全部归他直接管理,
也意味着,习大大要管理中国14亿人口,那这样不好吗?
如果这样,管理起来是不是很不方便?

对于程序来讲,如果你写一个程序,程序写大了之后,如果不做分片管理,可能会出现不可控的现象,
换言之,对于一个省,一个人能管理得那么多?管理不过来吧?
所以采取了一种方式,分为几十个省。

每个省长都认识习大大,而为什么每个省下的每个市长认识习大大,而习大大不认识这些市长?
假如说,省长是习大大的下一代(son),那么市长就是习大大的下下代(grandson),因为
每个省长自己有太多的下一代(son),意味着习大大有太多的下下代(grandson),所以
习大大认不过来。虽然习大大不知道这些市长是谁,但是他肯定知道这些市长是属于他管理的
,他们之间总有一种联系,一种归属联系,谁属于谁。

又比如说,长沙市,长沙市属于湖南,湖南属于中国,比如长沙和北京,它们之间是不是有
共同性,都属于中国,但是他们也有不同,地理位置不同,人口数量不同,方言不同。也就是说,
他们有相同性,也有不同性。

放在计算机的世界里,通过面向对象编程,可以实现程序之间有一些共同性,也可以衍生
出一些不同性。

世界万物,皆可分类

比如说,猫、狗、熊猫、狮子 等是不是都是动物,那么我们是不是可以把它们归为一类,
都是动物,即动物 包括 猫 狗 熊猫 狮子 等....

人也可以分类:男人、女人  或者 好人、坏人

那么问题来了,什么是类?

从上面的例子,不难知道,

人、动物、 ... 就是一个类

什么是对象?

对象即类的实体,一个叫老六很漂亮的女人(这就是一个对象)

什么是方法?

人会走、会跑、会思考   狗会叫、会啃骨头、会咬人 (定义一个类的各个功能,方法)

什么是继承?

人都有手有脚(继承它的父母)

什么是封装?

人不能引用狮子的特性,比如4条腿走路

什么是多态性?

一个叫的功能,可能低吼、可能大声叫

什么是抽象性?

简化复杂的现实的问题途径,可以给任何问题找到恰当的类定义
比如:空气 ,看不见,摸不着,我们也可以给它一个类,"气体"

在程序的世界里:

类就是一个模板,模板里可以包含多个函数,函数里实现一些功能

对象则是根据模板创建的实例,通过实例对象可以执行类中的函数

那么该如何定义一个类?

类是对现实世界中一些事物的封装,定义一个类可以采用下面的方式来定义:

class className:
    block

注意类名后面有个冒号,在block块里面就可以定义属性和方法了。当一个类定义完之后,就产生了一个类对象。类对象支持两种操作:引用和实例化。引用操作是通过类对象去调用类中的属性或者方法,而实例化是产生出一个类对象的实例,称作实例对象。比如定义了一个People类:

class People:
    name = 'allen'         #定义了一个属性
    def MyName(self):      #函数,在类中就是一个方法
        print self.name

People类定义完了之后就产生了一个全局的类对象,可以通过类对象来访问类中的属性和方法了。
当通过People.name来访问时,People.name中的People称为类对象,当然还可以进行实例化操作,P1= People(),这样就产生了一个People的实例对象P1,此时也可以通过实例对象P1来访问属性或者方法了(P1.name)

注意:上面的例子中,name是一个属性,函数Myname()是一个方法,一般在类里面定义的函数与类
对象或者实例对象绑定了,所以称作为方法;而在类外定义的函数一般没有同对象进行绑定,就称为函数。

属性:

在类中,我们可以定义一些属性:

class People:
    name = 'allen'
    age = 25

P1 = People()      #实例化了一个对象P1
print P1.name      #然后就可以通过P1来读取属性了
print P1.age

# name , age 是类的公有属性
# 可以直接在类外通过对象名访问,私有属性,需在前面加2个下划线“__”即可。
class People:
    __name = 'allen'
    __age = 25

P1 = People()
print P1.__name    #访问类的私有属性
print P1.__age     #访问类的私有属性

# 以上访问会报错

执行结果报错如下

Allen:~ $ python test1.py
Traceback (most recent call last):
  File "test1.py", line 9, in <module>
    print P1.__name
AttributeError: People instance has no attribute '__name'
提示找不到该属性,因为私有属性是不能够在类外通过对象名来进行访问的。

方法:

在类中可以根据需要定义一些方法,定义方法采用def关键字,在类中定义的方法至少会有一个参数,,一般以名为'self'的变量作为该参数(用其他名称也可以),而且需要作为第一个参数。

class People:
    __name = 'allen'
    __age = 25

    def MyName(self):  #self 作为参数
        return self.__name
    def MyAge(self):
        return self.__age

P1 = People()
print "my name is: %s, age is: %s" % (P1.MyName(),P1.MyAge())

self,可以把它当做指针理解,就是对象自身的意思,在用某个对象调用该方法时,就将该对象
作为第一个参数传递给self。

执行结果如下:

Allen:~ $ python test1.py
my name is: allen, age is: 25

类中内置的一些方法

在Python中有一些内置的方法,这些方法一般是以 2个下划线开始然后以2个下划线结束。
类中最常用的就是构造方法和析构方法。

我们一般看到的比较多的 __init__(self,name,age,...) 就是构造方法
构造方法在生成对象时调用,可以用来进行一些初始化操作,不需要显示去调用,
系统会默认去执行。构造方法支持重载,如果用户自己没有重新定义构造方法,
系统就自动执行默认的构造方法。

而__del__(self) 也就是析构方法,在释放对象时调用,支持重载,可以在里面进行
一些释放资源的操作,不需要显示调用。

类属性、实例属性

顾名思义,类属性就是类对象所拥有的属性(我们上面觉得例子就是类属性),它被所有类对象的实例对象所共有,在内存中只存在一个副本,对于类的共有属性,在类外可以通过类对象和实例对象访问。

关于类的属性的访问,请看以下例子

class People:
    name1 = 'allen'        #类的共有属性
    __name2 = 'yyh'        #类的私有属性

P1 = People()              #P1,实例化后的对象
print P1.name1             #正确
print People.name1         #正确
print P1.__name2           #错误,不能在类外通过实例对象访问类的私有属性
print People.__name2       #错误,不能在类外通过类对象访问类的私有属性

实例属性是可以通过赋值定义的:

class People:
    name = 'allen'

P1 = People()
P1.age = 25                 #给P1对象添加一个实例属性age,赋值为25
print P1.name               #正确
print P1.age                #正确

print People.name           #正确
print People.age            #错误  

在类外对类对象People进行实例化产生P1,然后P1.age = 25 相当于 P1 添加了一个实例属性
age,并且赋值为25。这个实例属性是实例对象P1所特有的,但是,类对象People并没有拥有它
所以不能通过类对象来访问这个age属性,当然还可以在实例化对象的时候给age赋值。

class People:
    name = 'allen'
    def __init__(self,age): #是内置的构造方法,在实例化对象时自动调用
        self.age = age

P1 = People(25)             #实例化对象,并赋值
print P1.name               #正确
print P1.age                #正确

print People.name           #正确
print People.age            #错误  

如果需要在类外修改类属性,必须通过类对象去引用然后进行修改。如果通过实例对象去引用,会产生一个同名的实例属性,这种方式修改的是实例属性,不会影响到类属性,并且之后如果通过实例对象去引用该名称的属性,实例属性会强制屏蔽掉类属性,即引用的是实例属性,除非删除了该实例属性。

class People:
    name = 'allen'

print "This is People.name: %s" % People.name  #访问类属性

P1 = People()
print "This is before p1.name: %s" % P1.name   #访问实例属性

P1.name = 'yyh'
print "This is modify after name %s" % P1.name #通过实例对象修改的只是实例属性

print "This is People.name: %s" % People.name  #访问类属性,在下面的结果可以看
                    到,通过实例对象去修改的时候修改的只是实例属性,类属性并没有被改变

del P1.name                                    #删除修改过的实例属性
print "This is del P1.name: %s" % P1.name      #访问实例属性,此时发现之前修改,
                                                以被删除

打印结果如下:

Allen:~ $ python test1.py
This is People.name: allen
This is before p1.name: allen
This is modify after name yyh    #修改的只是实例属性
This is People.name: allen       #类属性并没有被修改
This is del P1.name: allen

类方法、静态方法、实例方法<普通方法>

类方法:

是类对象所拥有的方法,需要用修饰器"@classmethod"来装饰,对于类方法,第一个参数必须
是类对象,一般以"cls"作为第一个参数,执行类方法时,自动将调用该方法的类复制给cls。
重点:能够通过实例对象和类对象去访问。

class People:
    name = 'allen'
    
    @classmethod          #用classmethod来进行装饰
    def getName(cls):     #类方法,默认参数:cls
        return cls.name

P1 = People()
print P1.getName()        #可以通过实例对象访问
print People.getName()    #可以通过类对象访问

通过类方法可以对类属性进行修改:

class People:
    name = 'allen'   
    
    @classmethod           #类方法,用classmethod来进行装饰
    def getName(cls):      
        return cls.name
        
    @classmethod           #类方法,用classmethod来进行装饰
    def setName(cls,name):
        cls.name = name
        

P1 = People()
print "Before P1.getName :%s" % P1.getName()             #可以通过实例对象访问
print "Before People.getNmae: %s" % People.getName()     #可以通过类对象访问

P1.setName('yyh')                                        #传参

print "After P1.getName: %s" % P1.getName()   
print "After People.getName: %s" % People.getName()    

执行结果如下:

Allen:~ $ python test1.py
Before P1.getName :allen
Before People.getNmae: allen
After P1.getName: yyh       
After People.getName: yyh  #可以看到类属性已经改变

静态方法:

需要通过修饰器"@staticmethod"来进行装饰,静态方法不需要多定义参数。

class People:
    name = 'allen'
    
    @staticmethod          #通过staticmethod装饰器装饰  
    def getName():         #静态方法,无默认参数
        return People.name
      
print People.getName()     

实例方法<普通方法>:

类中最常定义的方法,它至少有一个参数并且必须以实例对象作为其第一个参数,一般以名为'self'的变量作为第一个参数(也可其他参数),在类外,实例方法只能通过实例对象去调用,不能通过其他方式去调用。

class People:
    name = 'allen'
     
    def getName(self):     #实例方法
        return self.name
        

P1 = People()
print P1.getName()         #正确,可以通过实例对象访问实例方法
print People.getName()     #错误,不能通过类对象访问实例方法

执行结果如下:

Allen:~ $ python test1.py
allen  #正常访问,没有报错  
Traceback (most recent call last):
  File "test1.py", line 86, in <module>
    print People.getName()
TypeError: unbound method getName() must be called with 
People instance as first argument (got nothing instead)   
      #报错,因为不能通过类对象访问实例方法

(今天就暂时讲这么多了,关于继承、将在下一章节中讲解)

你可能感兴趣的:(初识面向对象编程)