質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.37%

  • Python 3.x

    2398questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • 機械学習

    267questions

    機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

python3のコードの振る舞いがわからないので教えていただけますでしょうか。

解決済

回答 1

投稿 2017/11/20 00:33

  • 評価
  • クリップ 0
  • VIEW 74

mmmisaki

score 2

前提・実現したいこと

python3のコードの振る舞いがいまいちわからないです

以下のコードの
best = genetic.get_best(fnGetFitness, len(target), optimalFitness,self.geneset, fnDisplay)
という関数の部分なんですがget_best関数に渡すfnGetFitness,fnDisplayの引数が定義されてないままget_best関数に渡しているように見えます。
実際直前にprintで引数を出力させても
<function GuessPasswordTests.guess_password.<locals>.fnGetFitness at 0x7f8edfe44378>
38
38
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!.,
<function GuessPasswordTests.guess_password.<locals>.fnDisplay at 0x7f8edfe446a8>
5
(5つprintしたのに6つ出力されているのも何故なんでしょうか)
となります。

呼び出されたget_best関数内で引数を出力しても同様<functin 以下略>となります。しかし最終的にはしっかり文字列が出力されています。

unittestだと特別な処理方法をしてコードの実行順番が違うのか わからなくて困っております。
以下の実際のコードの振る舞いを教えていただけますでしょうか。

実際のコード

import datetime
import random
import unittest

import genetic


def get_fitness(guess, target):
    return sum(1 for expected, actual in zip(target, guess)
               if expected == actual)


def display(candidate, startTime):
    timeDiff = datetime.datetime.now() - startTime
    print("{}\t{}\t{}".format(
        candidate.Genes, candidate.Fitness, timeDiff))


class GuessPasswordTests(unittest.TestCase):
    geneset = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!.,"

    def test_Hello_World(self):
        target = "machine learning in genetic algorithm!"
        self.guess_password(target)

    def guess_password(self, target):
        startTime = datetime.datetime.now()

        def fnGetFitness(genes):
            return get_fitness(genes, target)

        def fnDisplay(candidate):
            display(candidate, startTime)
        optimalFitness = len(target)
      #  print(fnGetFitness)
       # print(len(target))
       # print(optimalFitness)
       # print(self.geneset)
       # print(fnDisplay)
        best = genetic.get_best(fnGetFitness, len(target), optimalFitness,
                                self.geneset, fnDisplay)
        self.assertEqual(best.Genes, target)


if __name__ == '__main__':
    unittest.main()
import random
import statistics
import sys
import time

def _generate_parent(length, geneSet, get_fitness):
    genes = []
    while len(genes) < length:
        sampleSize = min(length - len(genes), len(geneSet))
        genes.extend(random.sample(geneSet, sampleSize))
    genes = ''.join(genes)
    fitness = get_fitness(genes)
    return Chromosome(genes, fitness)


def _mutate(parent, geneSet, get_fitness):
    index = random.randrange(0, len(parent.Genes))
    childGenes = list(parent.Genes)
    newGene, alternate = random.sample(geneSet, 2)
    childGenes[index] = alternate if newGene == childGenes[index] else newGene
    genes = ''.join(childGenes)
    fitness = get_fitness(genes)
    return Chromosome(genes, fitness)


def get_best(get_fitness, targetLen, optimalFitness, geneSet, display):

    random.seed()
    bestParent = _generate_parent(targetLen, geneSet, get_fitness)
    display(bestParent)
    if bestParent.Fitness >= optimalFitness:
        return bestParent
    while True:
        child = _mutate(bestParent, geneSet, get_fitness)
        if bestParent.Fitness >= child.Fitness:
            continue
        display(child)
        if child.Fitness >= optimalFitness:
            return child
        bestParent = child

class Chromosome:
    def __init__(self, genes, fitness):
        self.Genes = genes
        self.Fitness = fitness


class Benchmark:
    @staticmethod
    def run(function):
        timings = []
        stdout = sys.stdout
        for i in range(100):
            sys.stdout = None
            startTime = time.time()
            function()
            seconds = time.time() - startTime
            sys.stdout = stdout
            timings.append(seconds)
            mean = statistics.mean(timings)
            if i < 10 or i % 10 == 9:
                print("{} {:3.2f} {:3.2f}".format(
                    1 + i, mean,
                    statistics.stdev(timings, mean) if i > 1 else 0))

補足情報(言語/FW/ツール等のバージョンなど)

python3

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

Pythonでは関数もオブジェクトの一つなので、そのまま渡せます。

def high(func):
    func('spam')

def hoge(s):
    print(s * 2)

def fuga(s):
    print(s[:-1])

high(hoge)
high(fuga)

"""出力
spamspam
spa
"""

これはかなりシンプルな例ですが、引数は呼び出す際にあればよいことが分かります。

ご提示のコードの挙動を完全に理解するには、クロージャについて知る必要がありますが...
まあ、とりあえず『関数そのもの』を渡していることがわかれば大丈夫です。


get_best関数内で引数を出力しても同様<functin 以下略>となります

『関数そのもの』を出力すると、そのように表示されます。至って正常な動作です。

>>> print(hoge)
<function hoge at 0x0000020E078FBAE8>

5つprintしたのに6つ出力されているのも何故なんでしょうか

試してみましたが、最後の『5』は表示されませんでした。
なにか別の出力を混同したのではないでしょうか?

投稿 2017/11/20 00:48

編集 2017/11/20 00:52

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/20 00:59

    お早い回答ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.37%

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    2398questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • 機械学習

    267questions

    機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。