'python面試題之@classmethod, @staticmethod, @property?'

Python 人生第一份工作 程序員亮哥 2019-09-07
"

回答背景知識

這些都是裝飾器(decorator)。裝飾器是一種特殊的函數,要麼接受函數作為輸入參數,並返回一個函數,要麼接受一個類作為輸入參數,並返回一個類。

@標記是語法糖(syntactic sugar),可以讓你以簡單易讀得方式裝飾目標對象。

@my_decorator
def my_func(stuff):
do_things
Is equivalent to
def my_func(stuff):
do_things
my_func = my_decorator(my_func)

你可以在本網站上找到介紹裝飾器工作原理的教材。

真正的答案

@classmethod, @staticmethod和@property這三個裝飾器的使用對象是在類中定義的函數。下面的例子展示了它們的用法和行為:

class MyClass(object):
def __init__(self):
self._some_property = "properties are nice"
self._some_other_property = "VERY nice"
def normal_method(*args,**kwargs):
print "calling normal_method({0},{1})".format(args,kwargs)
@classmethod
def class_method(*args,**kwargs):
print "calling class_method({0},{1})".format(args,kwargs)
@staticmethod
def static_method(*args,**kwargs):
print "calling static_method({0},{1})".format(args,kwargs)
@property
def some_property(self,*args,**kwargs):
print "calling some_property getter({0},{1},{2})".format(self,args,kwargs)
return self._some_property
@some_property.setter
def some_property(self,*args,**kwargs):
print "calling some_property setter({0},{1},{2})".format(self,args,kwargs)
self._some_property = args[0]
@property
def some_other_property(self,*args,**kwargs):
print "calling some_other_property getter({0},{1},{2})".format(self,args,kwargs)
return self._some_other_property
o = MyClass()
# 未裝飾的方法還是正常的行為方式,需要當前的類實例(self)作為第一個參數。
o.normal_method
# <bound method MyClass.normal_method of <__main__.MyClass instance at 0x7fdd2537ea28>>
o.normal_method()
# normal_method((<__main__.MyClass instance at 0x7fdd2537ea28>,),{})
o.normal_method(1,2,x=3,y=4)
# normal_method((<__main__.MyClass instance at 0x7fdd2537ea28>, 1, 2),{'y': 4, 'x': 3})
# 類方法的第一個參數永遠是該類
o.class_method
# <bound method classobj.class_method of <class __main__.MyClass at 0x7fdd2536a390>>
o.class_method()
# class_method((<class __main__.MyClass at 0x7fdd2536a390>,),{})
o.class_method(1,2,x=3,y=4)
# class_method((<class __main__.MyClass at 0x7fdd2536a390>, 1, 2),{'y': 4, 'x': 3})
# 靜態方法(static method)中除了你調用時傳入的參數以外,沒有其他的參數。
o.static_method
# <function static_method at 0x7fdd25375848>
o.static_method()
# static_method((),{})
o.static_method(1,2,x=3,y=4)
# static_method((1, 2),{'y': 4, 'x': 3})
# @property是實現getter和setter方法的一種方式。直接調用它們是錯誤的。
# “只讀”屬性可以通過只定義getter方法,不定義setter方法實現。
o.some_property
# 調用some_property的getter(<__main__.MyClass instance at 0x7fb2b70877e8>,(),{})
# 'properties are nice'
# “屬性”是很好的功能
o.some_property()
# calling some_property getter(<__main__.MyClass instance at 0x7fb2b70877e8>,(),{})
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: 'str' object is not callable
o.some_other_property
# calling some_other_property getter(<__main__.MyClass instance at 0x7fb2b70877e8>,(),{})
# 'VERY nice'
# o.some_other_property()
# calling some_other_property getter(<__main__.MyClass instance at 0x7fb2b70877e8>,(),{})
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# TypeError: 'str' object is not callable
o.some_property = "groovy"
# calling some_property setter(<__main__.MyClass object at 0x7fb2b7077890>,('groovy',),{})
o.some_property
# calling some_property getter(<__main__.MyClass object at 0x7fb2b7077890>,(),{})
# 'groovy'
o.some_other_property = "very groovy"
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# AttributeError: can't set attribute
o.some_other_property
# calling some_other_property getter(<__main__.MyClass object at 0x7fb2b7077890>,(),{})
"

相關推薦

推薦中...