我有一個配置類。我希望它有幾種方法,這取決于類的另一個變數。這樣我只需要更改配置類中的一個變數,然后它就會以不同的方式運行。
我嘗試了以下。創建實體時,我可以訪問 other_param,但目標函式丟失了。
class Config:
def __init__(self):
self.task = 'Task1'
if self.task=='Task1':
self.other_param = 1
def objective(self,probs):
return probs[0]
if self.task=='Task2':
self.other_param = 2
def objective(self,probs):
return probs[1]
事實上,我可以通過反轉邏輯來獲得解決方案,即定義一個方法并在其中包含一個 if 陳述句。但是我希望每個 if 分支都有幾種方法......而且我不想讓所有這些方法都充滿 if 陳述句。如果屬于同一個 if 分支的所有方法都在同一個地方,那么代碼將更具可讀性。
uj5u.com熱心網友回復:
這樣的事情應該可以解決您的問題:
class Config:
def __init__(self, task: str):
self.task = task
if self.task == 'Task1':
self.other_param = 1
self.objective = lambda probs: probs[0]
elif self.task == 'Task2':
self.other_param = 2
self.objective = lambda probs: probs[1]
>>> a = Config('Task1')
>>> a.objective([1,2])
1
>>> a = Config('Task2')
>>> a.objective([1,2])
2
對于多行功能:
class Config:
def __init__(self, task: str):
self.task = task
if self.task == 'Task1':
self.other_param = 1
def objective(probs):
...
return probs[0]
self.objective = objective
elif self.task == 'Task2':
self.other_param = 2
def objective(probs):
...
return probs[1]
self.objective = objective
請注意,self在函式中隱式宣告,objective可以在其中直接訪問。
uj5u.com熱心網友回復:
我會在這里使用簡單的類派生,在基類中使用靜態構建方法。
class Config:
# _subs = {"Task1": Config1, 'Task2': Config2} # subclasses are not defined yet
@classmethod
def build(cls, task):
return cls._subs[task]()
conf.otherparam = task[-1] # or whatever common initialization
class Config1(Config):
def objective(self, probs):
return probs[0]
class Config2(Config):
def objective(self, probs):
return probs[1]
# set _subs static member once subclasse have been defined
Config._subs = {"Task1": Config1, 'Task2': Config2}
然后你可以使用
conf1 = Config.build('Task1')
conf1.objective(probs)
...
您可以使基類抽象以確保objective被覆寫。
uj5u.com熱心網友回復:
我認為任何避免在類上使用條件定義方法的方法都比這樣做更好。
查看您的示例代碼,它可以寫成:
class Config:
def __init__(self):
self.task = 'Task1'
self._probs_index = 0
if self.task == 'Task1':
self.other_param = 1
if self.task == 'Task2':
self.other_param = 2
self._probs_index = 1
def objective(self, probs):
return probs[self._probs_index]
可能您的真實代碼更復雜,您會說這對您不起作用。
但我建議不惜一切代價避免你目前正在嘗試做的事情。
目前尚不清楚您的真實代碼中是否task為 arg __init__(該示例目前沒有多大意義)
如果是這樣,我們可能會將上面的內容重寫為:
class Config:
def __init__(self, task):
self.task = task
# default values
self._probs_index = 0
self.other_param = 0
if self.task == 'Task1':
self.other_param = 1
elif self.task == 'Task2':
self.other_param = 2
self._probs_index = 1
else:
# unexpected value, choose here if you want to
# continue and use defaults or raise an error
raise ValueError(f"Unexpected task: {task}")
def objective(self, probs):
return probs[self._probs_index]
如果不是,那么我們可以將它們視為子類。將具有相關但不同行為的類視為子類是很自然的。
from abc import ABC, abstractmethod
class BaseConfig(ABC):
task = None # overwrite in sub-classes
# default values, overwrite in sub-classes if needed
other_param = 0
@abstractmethod
def objective(self, probs):
pass
class Task1Config(BaseConfig):
task = "Task1"
other_param = 1
def objective(self, probs):
return probs[0]
class Task2Config(BaseConfig):
task = "Task2"
other_param = 2
def objective(self, probs):
return probs[1]
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/521494.html
標籤:Python班级方法
