Python面向對象編程(一)

一.什麼是面向對象的程序設計爲什麼要有它

1.面向過程的程序設計:核心是過程二字,過程指的是解決問題的步驟,即先幹什麼再幹什麼......面向過程的編程就好比設計一條流水線,是一種機械式的思維方式。

優點是:複雜的問題流程化,進而簡單化

缺點是:一套流水線或者流程就是用來解決一個問題,生產汽水的流水線無法生產汽車,即便是能,也得是大改,改一個組件,牽一髮而動全身。

應用場景:一旦完成基本很少改變的場景,著名的例子有Linux內核,git,以及Apache HTTP Server等


2.面向對象的程序設計:核心是對象二字,對象是特徵與技能的結合體,基於面向對象設計程序就好比在創造一個世界,你就是這個世界的上帝,存在的皆爲對象,不存在的也可以創造出來,與面向過程的思維方式形成鮮明的對比,面向對象更加重視對現實世界的模擬,是一種“上帝式”的思維方式

優點是:解決了程序的擴展性。對某一個對象單獨修改,會立刻反應在整個體系中。

缺點是:編程複雜度遠高於面向過程

應用場景:需求經常變化的軟件,一般需求的變化都集中在用戶層,互聯網應用,企業內部軟件,遊戲等都是面向對象的程序設計大顯身手的好地方


二.類與對象

     類:對象是特徵與技能的結合體,而類則是一系列對象相同的特徵與技能的結合體

     強調:       

        1.對象是具體存在的事物,而類則一個抽象的概念

        2.站在不同的角度總結出的類與對象是不同的

        在現實世界中:先有一個個具體存在的對象,然後隨着人類文明的發展才總結出類的概念

        在程序中: 先定義類,後調用類來產生對象

1.先定義類
  class OldboyStudent:
    #相同的特徵
    school = 'oldboy'

    #相同的技能
    def choose_course(self):
        print('choosing course')
#類是一系列對象相同的特徵(變量)與技能(函數)的結合體,即類體中最常見的就是變量與函數的定義
# 但其實類體中是可以存在任意python代碼的
# 類體代碼會在類定義階段立即執行,會產生一個類名稱空間,用來將類體代碼執行過程中產生的名字都丟進去,查看方式如下
# print(OldboyStudent.__dict__) # 查看類的名稱空間
# print(OldboyStudent.school) #print(OldboyStudent.__dict__['school'])
# print(OldboyStudent.choose_course)
# OldboyStudent.school='OLDBOY' #OldboyStudent.__dict__['school']='OLDBOY'
# OldboyStudent.country='China' #OldboyStudent.__dict__['country']='China'
# del OldboyStudent.country # del OldboyStudent.__dict__['country']
# print(OldboyStudent.__dict__) 
# 總結:
#1. 類本質就是一個名稱空間,或者說是一個用來存放變量與函數的容器
#2. 類的用途之一就是當做名稱空間從其內部取出名字來使用
#3. 類的用途之二是調用類來產生對象 


2.後調用類來產生對象
# s1=OldboyStudent()
# s2=OldboyStudent()
# s3=OldboyStudent()
#如此,s1、s2、s3都一樣了,而這三者除了相似的屬性之外還各種不同的屬性,這就用到了__init__
#注意:該方法是在對象產生之後纔會執行,只用來爲對象進行初始化操作,可以有任意代碼,但一定不能有返回值
class OldboyStudent:
    ......    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex
    ......


s1=OldboyStudent('李坦克','男',18) #先調用類產生空對象s1,然後調用OldboyStudent.__init__(s1,'李坦克','男',18)s2=OldboyStudent('王大炮','女',38)
s3=OldboyStudent('牛榴彈','男',78)#程序中對象的用法#執行__init__,s1.name='牛榴彈',很明顯也會產生對象的名稱空間s2.__dict__{'name': '王大炮', 'age': '女', 'sex': 38}

s2.name #s2.__dict__['name']s2.name='王三炮' #s2.__dict__['name']='王三炮's2.course='python' #s2.__dict__['course']='python'del s2.course #s2.__dict__.pop('course')

 !!!細說_init__方法!!!

#  方式一:爲對象初始化自己獨有的特徵
class People:
    country='China'
    x=1
    def run(self):
        print('----->', self) 
# 實例化出三個空對象
obj1=People()
obj2=People()
obj3=People() 
 
# 爲對象定製自己獨有的特徵
obj1.name='egon'
obj1.age=18
obj1.sex='male'

obj2.name='lxx'
obj2.age=38
obj2.sex='female'

obj3.name='alex'
obj3.age=38
obj3.sex='female'

# print(obj1.__dict__)
# print(obj2.__dict__)
# print(obj3.__dict__)
# print(People.__dict__)

# 方式二、爲對象初始化自己獨有的特徵
class People:
    country='China'
    x=1

    def __init__(obj, x, y, z): #obj=obj1,x='egon',y=18,z='male'
        obj.name = x
        obj.age = y
        obj.sex = z

    def run(self):
        print('----->', self)

obj1=People('egon',18,'male') #People.__init__(obj1,'egon',18,'male')
obj2=People('lxx',38,'female') #People.__init__(obj2,'lxx',38,'female')
obj3=People('alex',38,'female') #People.__init__(obj3,'alex',38,'female')

# __init__方法
# 強調:
#   1、該方法內可以有任意的python代碼
#   2、一定不能有返回值
class People:
    country='China'
    x=1
    def __init__(obj, name, age, sex): #obj=obj1,x='egon',y=18,z='male'
        # if type(name) is not str:
        #     raise TypeError('名字必須是字符串類型')
        obj.name = name
        obj.age = age
        obj.sex = sex


    def run(self):
        print('----->', self)


# obj1=People('egon',18,'male')
# obj1=People(3537,18,'male')

# print(obj1.run)
# obj1.run() #People.run(obj1)
# print(People.run)

!!!__init__方法之爲對象定製自己獨有的特徵

三.屬性查找

類有兩種屬性:數據屬性和函數屬性

1.類的數據屬性是所有對象共享的

2.類的函數屬性是綁定給對象用的

#類的數據屬性是所有對象共享的,id都一樣
print(id(OldboyStudent.school))
print(id(s1.school))
print(id(s2.school))
print(id(s3.school))

**************
4377347328
4377347328
4377347328
4377347328
**************

#類的函數屬性是綁定給對象使用的,obj.method稱爲綁定方法,內存地址都不一樣
#ps:id是python的實現機制,並不能真實反映內存地址,如果有內存地址,還是以內存地址爲準

print(OldboyStudent.learn)
print(s1.learn)
print(s2.learn)
print(s3.learn)

*******************
<function OldboyStudent.learn at 0x1021329d8>
<bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x1021466d8>>
<bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146710>>
<bound method OldboyStudent.learn of <__main__.OldboyStudent object at 0x102146748>>
*******************

在obj.name會先從obj自己的名稱空間裏找name,找不到則去類中找,類也找不到就找父類...最後都找不到就拋出異常 

 

四.綁定到對象的方法的特殊之處

#改寫
class OldboyStudent:
    school='oldboy'
    def __init__(self,name,age,sex):
        self.name=name
        self.age=age
        self.sex=sex    
    def learn(self):        
        print('%s is learning' %self.name) #新增self.name    
    def eat(self):        
        print('%s is eating' %self.name)    
    def sleep(self):        
        print('%s is sleeping' %self.name)

s1=OldboyStudent('李坦克','男',18)
s2=OldboyStudent('王大炮','女',38)
s3=OldboyStudent('牛榴彈','男',78)

類中定義的函數(沒有被任何裝飾器裝飾的)是類的函數屬性,類可以使用,但必須遵循函數的參數規則,有幾個參數需要傳幾個參數

OldboyStudent.learn(s1) #李坦克 is learning
OldboyStudent.learn(s2) #王大炮 is learning
OldboyStudent.learn(s3) #牛榴彈 is learning

類中定義的函數(沒有被任何裝飾器裝飾的),其實主要是給對象使用的,而且是綁定到對象的,雖然所有對象指向的都是相同的功能,但是綁定到不同的對象就是不同的綁定方法

強調:綁定到對象的方法的特殊之處在於,綁定給誰就由誰來調用,誰來調用,就會將‘誰’本身當做第一個參數傳給方法,即自動傳值(方法__init__也是一樣的道理)



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章