代码之家  ›  专栏  ›  技术社区  ›  Neil G

python元编程:自动生成成员函数

  •  6
  • Neil G  · 技术社区  · 13 年前

    如何编写向类中添加方法的函数?我有:

    class A:
        def method(self):
            def add_member(name):
                self.new_method = def name...?
    
            add_member("f1")
            add_member("f2")
    

    为了回答我想做的事情。我正试图找出一些Pyqt槽。我想能够调用一个函数 create_slider 这将创建一个 QSlider 和A QLabel 并创建滑块处理代码,并使滑块处理程序更新 QLabor . 下面是需要考虑的插槽:

        def on_sample_slider(self, value):
            self.samples = pow(4, value)
            self.sample_label.setText('%d' % self.samples)
    

    下面是一个生成一些用户界面的方法,但是每次调用它时,最好也让它生成on-sample-slider方法:

        def insert_labeled_slider(hbox, name, slider_target):
            # name
            hbox.addWidget(QLabel(name))
    
            # label
            label = QLabel()
            label.setMinimumSize(40, 0)
            hbox.addWidget(self.sample_label)
    
            #slider
            slider = QSlider(Qt.Horizontal)
            slider.setRange(0, 6)
            slider.setTracking(True)
            slider.setPageStep(1)
            hbox.addWidget(slider)
    
            self.connect(self.sample_slider, SIGNAL('valueChanged(int)'),
                         self.on_sample_slider)
            self.sample_slider.setValue(0)
            return (label, slider)
    

    最终代码:

    def attach_on_slider(obj, name, variable, label, base):
        def on_slider(self, value):
            variable = base**value
            label.setText('%d' % variable)
    
        # This next line creates a method from the function
        # The first arg is the function and the second arg is the object
        # upon which you want it to be a method.
        method = types.MethodType(on_slider, obj)
        obj.__dict__["on_slider_" + name] = method
        return method
    
    class A:
        def insert_labeled_slider(hbox, name, label_name, variable):
            # name
            hbox.addWidget(QLabel(label_name))
    
            # label
            label = QLabel()
            label.setMinimumSize(40, 0)
            hbox.addWidget(label)
    
            #slider
            slider = QSlider(Qt.Horizontal)
            slider.setRange(0, 6)
            slider.setTracking(True)
            slider.setPageStep(1)
            hbox.addWidget(slider)
    
            on_slider_method = attach_on_slider(self, name, variable, label, 4)
    
            self.connect(slider, SIGNAL('valueChanged(int)'),
                         on_slider_method)
            slider.setValue(0)
            return (label, slider)
    
    2 回复  |  直到 12 年前
        1
  •  7
  •   aaronasterling    13 年前

    以下是您新发布的代码的一个真实示例:

    import types
    
    def attach_on_sample_slider(obj, base):
        def on_sample_slider(self, value):
            self.samples = base**value
            self.sample_label.setText('%d' % self.samples)
    
        # This next line creates a method from the function
        # The first arg is the function and the second arg is the object
        # upon which you want it to be a method.
        obj.on_sample_slider = types.MethodType(on_sample_slider, obj)
    

    你现在可以这样称呼它

    def some_method(self, foo):
        attach_on_sample_slider(self, 4)
    

    原帖

    既然你说成员函数是相同的,我会这样做

    def make_method(name):
        def method(self, whatever, args, go, here):
            #whatever code goes here
        method.__name__ = name
        return method
    
    
    class A(object):
        method1 = make_method('method1')
        method2 = make_method('method2') 
    

    严格来说,传递名字和设置 __name__ 新函数的属性不是必需的,但它可以帮助调试。它有点重复,而且可以自己付费。如果你想跳过这一点,你也可以跳过。

    class A(object):
        def method1(self, arg1, arg2):
            #code goes here
    
        method2 = method1
        method3 = method1 
    

    这将创建相同的方法。调用它们中的任何一个都将产生相同的方法。

    第一种形式更强大,因为您可以将除名称之外的其他参数传递到 make_method 并且让返回方法的不同版本在闭包中访问这些参数,这样它们的工作方式就不同了。下面是一个关于函数的愚蠢例子(与方法相同):

    def make_opener(filename):
        def opener():
            return open(filename)
        return opener
    
    open_config = make_opener('config.cfg')
    open_log = make_opener('log.log')
    

    在这里,它们基本上都是相同的功能,但是做的事情略有不同,因为它们可以访问 filename 它们是用它们创造的。如果你要做很多这样的事情,闭包绝对是值得研究的。

    还有很多问题要解决,所以如果你有一些特定的问题没有解决,你应该更新你的问题。

        2
  •  0
  •   Brent81    12 年前