python3中的可选yield或return。如何?

时间:2015-11-17 14:34:30

标签: python python-3.x return generator yield

我想有一个可以选择返回或产生结果的函数。 这是一个例子。

def f(option=True):
    ...
    for...:
        if option:
            yield result
        else:
            results.append(result)

    if not option:
        return results

当然,这不起作用,我尝试使用python3,无论我设置什么选项值,我总是得到一个生成器。 据我所知,python检查函数的主体,如果存在yield,则结果将是生成器。 有没有办法解决这个问题并制作一个可以随意返回或屈服的函数?

3 个答案:

答案 0 :(得分:19)

你做不到。 list()的任何使用都会使该函数成为生成器。

您可以使用def f_wrapper(option=True): gen = f() if option: return gen # return the generator unchanged return list(gen) # return all values of the generator as a list 来包装函数,以存储生成器在列表对象中生成的所有值并返回:

def f():
    yield result

def f_as_list():
    return list(f())

但是,一般来说,这是糟糕的设计。不要让你的功能改变这样的行为;坚持一种返回类型(生成器一个对象)并且不要在两者之间切换。

考虑将其拆分为两个函数:

f()

如果您需要生成器,请使用f_as_list();如果您想要列表,请使用list()

由于next(),(和# access elements one by one gen = f() one_value = next(gen) # convert the generator to a list all_values = list(f()) 只能访问生成器的一个值)是内置函数,因此您很少需要使用包装器。只需直接调用这些函数:

import javax.mail.*;
import javax.mail.internet.*;
import java.util.*;

public class SendEmail {

   final String senderEmailID = "Sender Email id";
final String senderPassword = "Sender Pass word";
final String emailSMTPserver = "smtp.gmail.com";
final String emailServerPort = "465";
String receiverEmailID = null;
static String emailSubject = "Test Mail";
static String emailBody = ":)";
public SendEmail(String receiverEmailID, String emailSubject, String emailBody)
{
this.receiverEmailID=receiverEmailID;
this.emailSubject=emailSubject;
this.emailBody=emailBody;
Properties props = new Properties();
props.put("mail.smtp.user",senderEmailID);
props.put("mail.smtp.host", emailSMTPserver);
props.put("mail.smtp.port", emailServerPort);
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.socketFactory.port", emailServerPort);
props.put("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory");
props.put("mail.smtp.socketFactory.fallback", "false");
SecurityManager security = System.getSecurityManager();
try
{
Authenticator auth = new SMTPAuthenticator();
Session session = Session.getInstance(props, auth);
MimeMessage msg = new MimeMessage(session);
msg.setText(emailBody);
msg.setSubject(emailSubject);
msg.setFrom(new InternetAddress(senderEmailID));
msg.addRecipient(Message.RecipientType.TO,
new InternetAddress(receiverEmailID));
Transport.send(msg);
System.out.println("Message send Successfully:)");
}
catch (Exception mex)
{
mex.printStackTrace();
}
}
public class SMTPAuthenticator extends javax.mail.Authenticator
{
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(senderEmailID, senderPassword);
}
}
    public static void main(String[] args) {
       SendEmail mailSender;
        mailSender = new SendEmail("Receiver Email id","Testing Code 2 example","Testing Code Body yess");
    }

}

答案 1 :(得分:1)

这个怎么样?

def make_f_or_generator(option):
    def f():
        return "I am a function."
    def g():
        yield "I am a generator."
    if option:
        return f
    else:
        return g

这至少为您提供了创建函数或生成器的选择。

答案 2 :(得分:0)

基于

class 的方法

class FunctionAndGenerator:
    def __init__(self):
        self.counter = 0
        
    def __iter__(self):
        return self
        

# You need a variable to indicate if dunder next should return the string or raise StopIteration. 
# Raising StopIteration will stop the loop from iterating more.
# You'll have to teach next to raise StopIteration at some point

    def __next__(self):
        self.counter += 1 
        if self.counter > 1 :
            raise StopIteration 
        return f"I'm a generator and I've generated {self.counter} times"        

    def __call__(self):
        return "I'm a function"
        
x = FunctionAndGenerator()
print(x())
    
for i in x:
    print(i)
I'm a function
I'm a generator and I've generated 1 times

[Program finished]