首頁  >  問答  >  主體

程式小白 問關於python當中類別的方法的參數問題

程式碼如下:

#
# -*- coding:gb2312 -*-
class CarStore(object):
    def order(self,car_type):
        return Factory.select(car_type)

class Factory(object):        
    def select(car_type):  #为什么这个地方的方法,没有self参数也可以运行?
        if car_type == "索纳塔":
            return Suonata()
        elif car_type == "名图":
            return Mingtu()
        else:
            print("没有您要的车型!")

class Car(object):
    def move(self):
        print("车在移动...")
    def music(self):
        print("正在播放音乐...")
    def stop(self):
        print("车在停止...")

class Suonata(Car):
    def __init__(self):
        print("索纳塔")

class Mingtu(Car):
    def __init__(self):
        print("名图")

car_store = CarStore()
suonata = car_store.order("索纳塔")
#car.move()
#car.music()
#car.stop()
suonata.move()

執行結果:

##這段程式碼本身是沒有問題,可以執行的。
我的問題是,為什麼第七行程式碼def select(car_type): 這個地方明明沒有self,也可以執行?我記得我在學類別的時候,被教育實例方法裡面每個方法都必須加上一個self的參數,這裡居然沒有,然後我在這個地方加上了self反而出錯了,如下圖:

結果反而運行出錯:

#為什麼會這樣?

#
欧阳克欧阳克2676 天前927

全部回覆(4)我來回復

  • 巴扎黑

    巴扎黑2017-06-22 11:54:02

    你是不是用的python3?
    在python3中,如果成員函數不加self,則代表函數是靜態成員函數,可以直接使用「類別名稱.函數名(參數)」的形式直接呼叫。
    但是如果你加了self,則這個函數為類的成員函數,在其他調用類中必須這樣調用:“類名.函數名(self,參數)”,或者在調用類類中實現一個實例,“實例名.函數名(參數)。

    python3是上述這樣,我的測試,在python2中不是。

    你在select函數中加了self,但是在 CarStore::order()中呼叫卻使用「類別名稱.函數名稱(參數)」的形式,所以不正確。你在CarStore::order()呼叫時改為「類別名稱.函數名稱(self,參數)」或在CarStore::order()實作一個實例,使用「實例名稱.函數名稱(參數)「這樣的形式試試。

    昨晚看到的,太晚了,所以今天早上測試的。

    回覆
    0
  • 三叔

    三叔2017-06-22 11:54:02

    self 不是魔法,
    改成什麼名字都可以的

    不一定要 self

    回覆
    0
  • 为情所困

    为情所困2017-06-22 11:54:02

    雷雷

    回覆
    0
  • PHP中文网

    PHP中文网2017-06-22 11:54:02

    class Factory(object):        
        def select(car_type):
            if car_type == "索纳塔":
                return Suonata()
            elif car_type == "名图":
                return Mingtu()
            else:
                print("没有您要的车型!")

    按這個寫法,select是物件方法,呼叫需要關聯一個實例Factory()。呼叫時物件實例是與第一個參數car_type綁定。這個參數名一般約定為self但是,不要求。

    你需要明白以下兩種呼叫方式是不同的:

    f = Factory()
    f.select(xxx)
    
    Factory.select(xxx)

    第一種方式,用實例物件去調用,第一個參數car_type自動與實例物件f綁定;
    第二種方式,用類別去調用,第一個參數(car_type)沒有綁定;你需要自己綁定才能不出錯-也就是你傳進去的car_typeFactory.selct(car_type)這行。

    但是,當你加上self後,這個函數有兩個參數,但是你只綁定了car_type,也就是綁定到第一個參數self,第二個沒有值,必然就出錯了。

    這裡你要做的其實是將select實作成類方法:

    class Factory(object):   
    
        @classmethod     
        def select(cls, car_type):
            if car_type == "索纳塔":
                return Suonata()
            elif car_type == "名图":
                return Mingtu()
            else:
                print("没有您要的车型!")

    那麼,以Factory.select(car_type)呼叫時,cls自動綁定到Factory,而car_type則綁定到car_type

    以上,無論是self還是cls,都只是約定的名字而已,起作用的是Python的類-對象-方法模型。

    建議可以看看《Python原始碼剖析》,至少要理解@classmethod是怎麼運作的,要不然是寫不好這類程式碼的。

    回覆
    0
  • 取消回覆