简体   繁体   中英

Is this a python decorators or python property?

I am a new python programmer, and I do not understand the mean of the code when reading the following code: @predict_all.property('sequences') . I find that python decorator almost is like the @decortor style. So I am confused about this code @predict_all.property('sequences') when there is a dot that is . following the @predict_all . Is this a python decorator or a python property?

@recurrent(states=['states', 'cells'], outputs=['destination', 'states', 'cells'])
    def predict_all(self, **kwargs):
        pre_emb = tuple(self.pre_context_embedder.apply(**kwargs))

        itr_in = tensor.concatenate(pre_emb + self.rec_input(**kwargs), axis=1)
        itr = self.input_to_rec.apply(itr_in)
        itr = itr.repeat(4, axis=1)
        (next_states, next_cells) = self.rec.apply(itr, kwargs['states'], kwargs['cells'], mask=kwargs['latitude_mask'], iterate=False)

        post_emb = tuple(self.post_context_embedder.apply(**kwargs))
        rto = self.rec_to_output.apply(tensor.concatenate(post_emb + (next_states,), axis=1))

        rto = self.process_rto(rto)
        return (rto, next_states, next_cells)

    @predict_all.property('sequences')
    def predict_all_sequences(self):
        return self.sequences

Supplementary information:

The origin of the problem, why do I ask this question?

When I learn about the decorator, I find that most tutorials show that the decorator is simple like this style: @timer , that is @ plus a functional name. And the property is like this style: @property , that is add @property before the method. So when I read the above code, I am confused what does this code @predict_all.property('sequences') meaning, I haven't seen this form of code before.So I am confused, is this code stand for a python decorator or a python property? I google it and find nothing about this style, that is @ plus . . So I post this question on Stack Overflow and hope to get the useful answer or comment.

The example code of python decorator I have learned as follows:

def timer(func): 
    def deco(*args, **kwargs):  
        start_time = time.time()
        func(*args, **kwargs)   
        stop_time = time.time()
        print("the func run time  is %s" %(stop_time-start_time))
    return deco  
@timer 
def test1():
    time.sleep(1)
    print('in the test1')

As Charles Duffy said, predict_all.property can be a function that returns a function that acts as a decorator.

You can take below's demo for your further understanding..

class Predict(object):
    def property(self, condition):
        def wrapper(fn):
            def inner(*args, **kw):
                if condition == 'sequences':
                    print("sequences")
                else:
                    print("else")
                return fn(*args, **kw)
            return inner
        return wrapper

predict_all = Predict() 


@predict_all.property("sequences")
def foo():
    pass

foo()

# result -- sequences


hope it helped

@ - applying decorator (syntactic sugar)

. - attribute access

decorator is something callable that returns something callable

propertiy is a specific kind of decorators, it is a class (descriptor) that returns object (descriptor object), in Python properties and descriptors are meant for attribute access control.

Now let's proceed to the question. Is @predict_all.property('sequences') is a python decorator or a python property? It's decorator. It's not property. predict_all returns object of Application class ( https://github.com/mila-iqia/blocks/blob/master/blocks/bricks/base.py#L68 ). Application class has method named property which is a regular decorator used to get class attributes by specified name.

You may also consider the following example of using decorators (try it online https://py3.codeskulptor.org/#user303_jaUkAvGSwi_4.py )

import time

def simple_decorator(func):
    def wrapper(*args, **kwargs):
        print('i am simple decorator', func, args, kwargs)
        return func(*args, **kwargs)
    return wrapper

@simple_decorator
def func_1(*args, **kwargs):
    print('i am func_1')

class DecoratorManager:

    def __init__(self):
        self.log = list()

    def not_that_simple_decorator(self, key):
        self.log.append((time.time(), key))
        def simple_decorator(func):
            def wrapper(*args, **kwargs):
                print('i am simple decorator', func, args, kwargs)
                return func(*args, **kwargs)
            return wrapper
        return simple_decorator

d_m = DecoratorManager()

@d_m.not_that_simple_decorator(key='pretty_key')
def func_2(*args, **kwargs):
    print('i am func_2')

def func_3(*args, **kwargs):
    print('i am func_3')

func_3 = d_m.not_that_simple_decorator(key='pretty_key')(func_3)

func_1(1, a=10)
func_2(2, b=20)
func_3(3, c=30)

print('decorator_manager_log:', d_m.log)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM