2017-01-21 5 views
1

関数に渡すことができるキーワード引数(または引数)があるか、または__init__のクラスのメソッドが常に奇妙に思えました。あなたのコードになじみのないユーザーが間違いを犯さないようにするにはどうすればよいですか?あなたのコードに慣れ親しんだ(ほとんど本能的に)慣れ親しんだ文書を書かなくても、長時間書かなくても、コードやモジュールを素早く快適に使用することを妨げる多くの試行錯誤にいかがでしょうか?Pythonのキーワード引数のエイリアス

私たちはhelpdirの機能を持っているので、私たちは幸いです。いくつかの関数のパラメータが何であるかをよりよく理解できるようにすることができます。しかし、時には何も書かれていない文字列が書かれていません。__doc__

は、私はあなたに私の言いたいことのいくつかの例を挙げてみましょう:

>>> help(str.lower) 
    Help on method_descriptor: 

     lower(...) 
     S.lower() -> string 

    Return a copy of the string S converted to lowercase 

。 例えば、...の入力パラメータを持つ関数があります。このパラメータが意味することは、完全な初心者のためで(私が最初にパイソンに飛び込んだときのように)これは混乱していて、たいていはこのセクションをスキップしました。

アドバイスやチュートリアルを提供するWebサイトの一部は、ヘルプ機能ファイルを出力するだけで、sed関数の多くの機能のうちの1つを実装するだけです。

1 functionality of example function

直接python.orgから

str.lower()
戻り[4]は小文字に変換され、すべてのケーシング文字と文字列のコピー。 8ビット文字列の場合、このメソッドはロケールに依存します。

今だけ(またはできない)ビットとバイトに飛び込む、アドレス、およびなどのプログラミング始めとそうでない誰かのために、これが唯一のウォーロックを行うことができ習得いくつかの古代の呪文で、でも私を聞かせていませんなぜこれが非英語圏の人々に役立っていないのかについて始めました。

この例の関数では、別の方法で仕事をすることができる2-3の追加の例を見つけることができます。また、この例の関数を文字列をstr.lower(here)部分に代入することによって使用できることがわかりました。

ここで大きな問題は(当然ですが)小さなグーグルの文字列はそれ自身で記述できることであり、その機能は論理的にはウィキペディア経由でしか結論できないということです。

質問をまとめると簡単ですが、パラメータとして使用するときにキーワードを変更して定義するよりも多くの名前を受け入れる方法があるので、導入チュートリアルの最初のステップでユーザーの髪を刈る必要はありません?

私は皆さんの中には、「あなたがそれを理解していなければ、それをしないでください」、あるいは「私はあなたにものを教えるためにママではありません。 「共有は気にしている」と言わなければなりません。「時には、このWebサイトにはないコーディングも必要です。

+0

申し訳ありませんが、これは私に*ひどい*アイデアのように聞こえる:

def __getitem__(self,item): if item in self.aliases.keys(): return getattr(self,item) if any(item in value for value in self.aliases.values()): item = [ key for key in self.aliases.keys() if item in self.aliases[key] ] [0] return getattr(self,item) if item in range(len(self.aliases.keys())): item = list(self.aliases.keys())[item] return getattr(self,item) 

はさらに__setitem__を説明します。関数は明確に定義された引数を取るべきであり、 "ユーザが(基本クラス名の論理)"を渡す引数のリストではない。 –

+0

私はタイプについては同意しますが、名前には同意しません。しかし、私はあなたがローカル変数に与えた名前が分からない場合、名前がわかっていれば明確に/厳密に定義されていれば、あなたは何を得ると思いますか? あなたはこの話題に長けていたいと思ったらチャットしています。私はあなたの視点については非常に興味があります。 – Danilo

答えて

1

コメントや訂正をした方がいい場合は、これは私の解決方法です。

アイデア:
アイデアは、ユーザーが(クラス名のロジックに基づいてことができるように、すべてのクラスは、特定の属性へのエイリアスのリストを持っている可能性があることです:>ポイントのニーズのX、Y、Z、名前属性、犬のニーズ名前、年齢、性別属性など)を、独自の内部ロジックに基づいて分類することができます。

ロジック:
機能またはクラスは、入力のために、いくつかのキーワード引数がある場合、私はsedの引数に関連付けられている一般的な単語の最小限のリストが必要になります。類義語とイディオムは簡単にグーグルで検索できますが、私は類義語の大きなリストに対してアドバイスします。
年代順に、我々は最初の別名を生成する関数を定義する必要があります。私たちはコードがgetattr(self,someattributestring)

コードを呼び出さずに属性を呼び出す方法を知っておく必要があるとして以来、その後、我々が必要とするすべてはマップに、元の属性にそれらの別名です。

# generate aliases for attributes 
def generateAliases(*argListNames): 

    returningValues = [] # this could be omitted if user wants to make generator 
    la = returningValues.append # this could be omitted also 

    #dominated argListNames 
    argListNames = map(str, argListNames) #for simplicity convert to strings 
    argListNames = map(str.lower , argListNames) #for simplicity convert to lower string 
    argListNames = list(argListNames) # back to list 

    # small nameless lambda functions 
    getFirstChr = lambda element: element[0] # getting first character 
    conectedJoing= lambda connector,item,args: connecter.join([ item, args if not __isTL__(args) else connecter.join(args) ]) # generating joined string 

    # list of string convertors used to generate aliases 
    convertorList= [ lambda x: x , getFirstChr , str.title , str.upper , lambda x: getFirstChr(str.upper(x)) ] 

    for item in argListNames: 
     ## since we dont want alias to repeat itself 
     listNoitem = filter(lambda x: x!=item , argListNames) 
     listNoitem = list(listNoitem) 

     la(item) # if returningValues omitted use yield statement 

     for conversion in convertorList: ##1 keeping up with for loops 
      converted = conversion(item) 

      for connecter in "_,".split(","): 

       for listItem in listNoitem: 

        for cnvrt in convertorList: ##2 cnvrt is converted second stage : used to convert the whole list of items without current alias 
         cList = cnvrt(listItem) 

         la(conectedJoing(connecter,converted,cList))# if returningValues omitted use yield statement 


       la(conectedJoing(connecter,converted,listNoitem))# if returningValues omitted use yield statement 

    # if user wanted to make generator omit next lines 
    returningValues = [ x.replace("_","") if x.endswith("_") else x for x in returningValues ] 
    returningValues = sorted(set(returningValues)) 
    return list(map(str,returningValues)) 

今、私たちは、私たちはいくつかの引数パーサが必要機能またはクラスの内側にこれらの引数をマッピングして確認する必要があります。クラスで実装される場合

python27 -m kwtest 
Process started >>> 
passed first as 1 (1, 1) 
passed second as 2 first as 3 (3, 2) 
passed f1 as 4 s2 as 5 (4, 5) 
passed 2_s as 7 f_1 as 6 (6, 7) 
<<< Process finished. (Exit code 0) 

python35 -m kwtest 
Process started >>> 
passed first as 1 (1, 1) 
passed first as 3 second as 2 (3, 2) 
passed f1 as 4 s2 as 5 (4, 5) 
passed f_1 as 6 2_s as 7 (6, 7) 
<<< Process finished. (Exit code 0) 

## **kwargs argument parser , no error 
def argumentParser(AprovedSequence,**kwargs): 

    # AprovedSequence is suposed to be dictionary data type with {"original argument": generateAliases(originalArgumentName,somealias,somealias,...) 

    """ 
     phrases the keyword arguments, 
      for example :  argumentParser(AprovedSequence,someArgument=somevalue,otherArgument=othervalue ...) 
     then it checks if someArgument is needed by checking in AprovedSequence if name "someArgument" is found in sequence: 
     If "someArgument" is found in AprovedSequence it stores returns dictionary of DefaultKeys : Values 
      for example: DefaultKey for someArgument: somevalue 

     input: 
      argumentParser(dict: AprovedSequence, kwargs) 
     returns: 
      dictionary of found attributes and their values 

     !!important!! kwargs are not case sensitive in this case , so go crazy as long as you get the apropriate keyword!! 
     if you dont know what kind of keywords are needed for class 
      just type className.errorAttributeNames() 
      for example point.errorAttributeNames() 

    """ 
    if isinstance(AprovedSequence,dict): 

     di = dict.items # dictionary.values(someDict) 
     dk = dict.keys # dictionary.keys(someDict) 

     # managing the kwargs and aprooved sequence data 
     toLowerStr = lambda el: str(el).lower() # conversion to lower string 
     asingKey = lambda el: [ key for key in dk(AprovedSequence) if toLowerStr(el) in AprovedSequence[key] ][0] # asigning key 

     return { asingKey(k):v for k,v in di(kwargs) } # dictionary comprehension 
    else: 
     raise TypeError("argumentPhraser function accepts only dictionary for a AprovedSequence aka first item") 
     return None 

実装

def somefunction(**kwargs): 
    aliases = { 
     "val1":generateAliases("first","1"), 
     "val2":generateAliases("second","2") 
    } 
    aproved = argumentParser(aliases,**kwargs) 

    if "val1" in aproved.keys(): val1 = aproved["val1"] 
    else: val1 = 0 # seting default value for val1 

    if "val2" in aproved.keys(): val2 = aproved["val2"] 
    else: val2 = 1 # seting default value for val2 

    #do something or your code here 

    return val1,val2 

# for testing purposes 
for x in [ {"first":1} , {"second":2,"first":3} , {"f1":4,"s2":5} , {"f_1":6,"2_s":7} ]: 
    # displaying imputed variables 
    form = ["passed "] 
    form += [ "{} as {} ".format(key,value) for key,value in x.items() ] 
    # implementing somefunciton 
    print("".join(form), somefunction(**x)) 

出力は、プロセスは__init__に類似しているが、それらはできるよう__getitem____setitem____delitem__は、符号化されなければなりませんサーチエイリアス内の属性名についても同様です。また、属性の名前はself.attributes = list(aliases.keys())などで生成される可能性があります。デフォルト値は__kwdefaults__、またはのデフォルトはのクラスに保存できます。

ご覧のとおり、このコードはpy2.7とpy3.5でテストされています。
必要なあなたはクラスのグローバル属性内または__init__内の別名を定義することができるかどう

さらに説明。 __getitem__さらに説明すると

def __setitem__(self,item,value): 
    item = self.__getitem__(self,item) 
    #? must have `__dict__` method or class needs to be instanced from object like class someclass(object) 
    item = [ key for key in vars(self).items() if self[key] == item] [0] 
    if item != None: 
     setattr(self,item,value) 
関連する問題