为什么我不能使用join来实现__str__的对象列表?

时间:2017-04-14 02:32:53

标签: python duck-typing

我正在学习Python中的鸭子打字,我知道如果你为一个类实现一些特殊的方法,你可以愉快地使用内置的类方法

例如:

private bool _isWorking;

private async void LineTrackListView_SelectionChangedAsync(object sender, SelectionChangedEventArgs e)
{
    if (_isWorking)
    {
        return;
    }

    _isWorking = true;

    // Removed some of your code here.

    listView.SelectedItem = -1;
    await Task.Delay(100);

    ChangePageToBusPage(selectedBusStopInListView.BusStop, selectedTrack);

    _isWorking = false;
}

如果我这样做,我可以使用import random import time import sys dare = ["try to drink a glass of water while standing on your hands", "Let the group deside your dare", "pose in an embarasing pose and take a picture", "kiss the person on your left", "let a person get your phone and text anyone in your contacts.", "do the worm", "lick the floor", "let the group give you a new hairstyle", "drag your butt on the floor and back", "do yoyr best impression of a baby being born", "let someone in the room give you a spanking", "make up a poem about whatever the group comes up with", "make everyone in the room smile", "let someone draw on your face with a pen"] d = ["dance with no music for", "curse like a sailor for", "pretend your a clown for", "make up an opera about anyone/anything for", "talk in a different accent for", "break dance for", "do the worm for", "do push ups for", "be someones pet for", "pole dance with an invisible pole for", "sing for", "belly dance for"] d_time = ["1 turn", "40 seconds", "3 turns", "25 seconds", "1 minute", "4 turns", "2 minutes", "5 minutes", "5 turns"] t = ["who would you want to make out with the most in the room?", "what was the stupidest thing youve ever done?", " if you were an animal, what would you be?", "if you could dye your hair any color, what would it be?", "what was the scariest dream youve had?", "who is the sexiest person here?", "who do you think would actidentaly kill someone in this room?", "who here has the nicest butt?", "how many lovers have you had?", "what is your biggest pet peeve", "who do you have a crush on atm?"] print("welcome to Truth or Dare!") def begin(): wow = input("[1] Truth, or [2] Dare?") if wow == '2': ch = random.randint(1, 2) if ch == 1: print(random.choice(dare)) time.sleep(1) br = input("did you ([1] chiken out?) or ([2] complete it?)") if br == '1': print("wow...") time.sleep(1) print("thats sad...") time.sleep(1) print("Next player!") time.sleep(1) begin() elif br == '2': print("wow!") time.sleep(1) print("nice!") time.sleep(1) print("Next player!") time.sleep(1) begin() elif ch == 2: print(random.choice(d),(random.choice(d_time)) time.sleep(1) br = input("did you ([1] chiken out?) or ([2] complete it?)") if br == '1': print("wow...") time.sleep(1) print("thats sad...") time.sleep(1) print("Next player!") time.sleep(1) begin() elif br == '2': print("wow!") time.sleep(1) print("nice!") time.sleep(1) print("Next player!") time.sleep(1) begin() elif wow == '1': print(random.choice(t)) time.sleep(1) br = input("did you ([1] chiken out?) or ([2] complete it?)") if br == '1': print("wow...") time.sleep(1) print("thats sad...") time.sleep(1) print("Next player!") time.sleep(1) begin() elif br == '2': print("wow!") time.sleep(1) print("nice!") time.sleep(1) print("Next player!") time.sleep(1) begin() begin() 和其他一些内置的方法,也可以做一些其他的东西,比如实现class A: def __init__(self,l): self._l = l def __iter__(self): return iter(self._l) ,所以我可以使用random.choice,随机.shuffle,我觉得python太酷了,但后来我发现了这个问题,我想使用join来打印一些我实现了for...in..,zip方法的对象,但是它没有工作

我发现这是因为当我们使用join时,我们会像__setitem__()一样编写它,所以鸭子打字技巧不会起作用,因为它使用str的方法而不是对象将被加入

但是为什么呢?因为很多人都采用专为鸭子打字而设计的方法,为什么不加入'?

@SethMMorton是我的疑问,谢谢 我知道我可以使用__str__来解决我的问题,但我不知道为什么python本身不会这样做?

2 个答案:

答案 0 :(得分:5)

回答“为什么”:Python中的所有内容都可转换为str,即使没有__str__,当repr表单为str时,也会使用对象的__str__请求。 Python可能很灵活,但你所描述的是弱类型(Python一般不做),而不是鸭子打字。 for的存在意味着你可以强制到一个字符串,但这并不意味着“是一个字符串”。

允许使用zip循环,str等迭代任意迭代不是弱类型,因为它是一个没有歧义的通用接口; iterables以相同的方式迭代,即使它们可能产生不同的类型。

实际的弱类型是危险的,因为它可以允许错误无声地传递。它在Python 3中尤为明显。如果允许自动强制转换为iterable_of_bytes_objects = b'123', b'456' ','.join(iterable_of_bytes_objects) ,那么你做了:

"b'123',b'456'"

你默默地产生b,当赔率是,你只是忘记了连接字符串上的前导b','.join(iterable_of_bytes_objects) ,并且意味着:

decode

或许你打算制作一个字符串,但忘了bytes repr。或许你想要每个对象的str,或者import this,或者其他什么。 Python根本不知道Python(','.join(map(str, iterable))):

  

面对模棱两可,拒绝猜测的诱惑。

以及:

  

明确比隐含更好。

Coercing会自动隐藏错误,并涉及人们“可能想要”的猜测性猜测。如果你想强迫,那就是li的用途,但这意味着你选择了一种特定的强制形式,而且假设你知道你正在做什么,这与其他禅宗要求相符:

  

错误绝不应该以无声方式传递。

     

除非明确沉默。

答案 1 :(得分:1)

这不是鸭子打字的问题。这是自定义系列类中包含的项目的问题。如果您尝试加入数字range(),则会收到相同的错误。而是这样做:

';'.join(str(i) for i in l)

这在string.join(iterable)的文档中有清楚的解释:“返回一个字符串,它是可迭代 iterable 中字符串的串联。”