一、classmethod(类方法)、staticmethod(静态方法)

方法包括:普通方法、类方法和静态方法,三种方法在内存中都归属于类,区别在于调用方式不同。

# 普通方法
由对象调用,至少一个self参数,执行普通方法时,自动将调用该方法的对象赋值给self。
# 类方法
由类调用,至少一个cls参数,执行类方法时,自动将调用该方法的类赋值给cls;当一个方法的操作只涉及静态属性的时候,就应该使用classmethod来装饰这个方法。
# 静态方法
由类调用,无默认参数;在面向对象的程序中,如果一个函数既和对象没有关系,也和类没有关系,那么就用staticmethod将这个函数变成一个静态方法。
class Person(object):
country = "美国" def __init__(self, name):
self.name = name def func(self):
"""定义普通方法,至少有一个self参数"""
print(self.name) @classmethod
def change_country(cls):
"""定义类方法,至少有一个cls参数"""
cls.country = "中国" @staticmethod
def sleep():
"""定义静态方法,无默认参数"""
print("正在睡觉...") person = Person("pd")
########## 调用普通方法 ##########
person.func() # pd ########## 调用类方法 ##########
Person.change_country() # 可以通过类的名字调用类方法
# person.change_country() # 还可以通过这个类创建出来的对象去调用类方法
print(Person.country) # 中国 ########## 调用静态方法 ##########
Person.sleep() # 通过类的名字去调用静态方法
person.sleep() # 通过实例对象去调用静态方法

相同点:对于所有的方法而言,均属于类(非对象)中;所以,在内存中也只保存一份。

不同点:方法调用者不同,调用方法时自动传入的参数不同。

二、property(属性)

属性非常简单,因为Python中的属性其实是普通方法的变种。

2.1 属性的基本使用

class Person(object):
def __init__(self, name):
self.name = name def func1(self):
print(self.name) @property # 定义属性
def func2(self):
print(self.name) obj = Person("pd") obj.func1() # pd
obj.func2 # 调用属性,结果同上

由属性的定义和调用要注意以下几点:

定义时,在普通方法的基础上添加 @property 装饰器
定义时,属性仅有一个self参数
调用时,无需括号
      方法:obj.func1()
      属性:obj.func2

属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象。

属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。

2.2 属性的两种定义方式

装饰器方式:在类的普通方法上应用装饰器

Python中的类有经典类和新式类,新式类的属性比经典类的属性丰富。(如果类继object,那么该类是新式类)

经典类,只有一种@property装饰器(如上面的示例那样)

新式类,具有三种@property装饰器

class Goods(object):
def __init__(self):
self.__price = 100 # 设定原价
self.discount = 0.8 # 设定折扣 @property
def price(self):
"""获取价格"""
return self.__price * self.discount @price.setter
def price(self, value):
"""设置价格"""
self.__price = value @price.deleter
def price(self):
"""删除商品原价这个属性"""
del self.__price obj = Goods()
print(obj.price) # 自动执行 @property 修饰的 price 方法,并获取方法的返回值
obj.price = 200 # 自动执行 @price.setter 修饰的 price 方法,并将200赋值给方法的参数
print(obj.price)
del obj.price # 自动执行 @price.deleter 修饰的 price 方法,删除商品原价这个属性
print(obj.price) # 报错,AttributeError: 'Goods' object has no attribute '_Goods__price'

静态字段方式:在类中定义值为property对象的静态字段

当使用静态字段的方式创建属性时,经典类和新式类无区别。

示例:

class Foo(object):

    def get_name(self):
return "pd" NAME = property(get_name) obj = Foo()
ret = obj.NAME # 自动调用func方法,并获取方法的返回值
print(ret) # pd

property的构造方法中有个四个参数:

第一个参数是方法名,调用 对象.属性 时自动触发执行方法
第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
第四个参数是字符串,调用 对象.属性.__doc__,此参数是该属性的描述信息
class Goods(object):
def __init__(self):
self.__price = 100 # 设定原价
self.discount = 0.8 # 设定折扣 def get_price(self):
"""获取价格"""
return self.__price * self.discount def set_price(self, value):
"""设置价格"""
self.__price = value def del_price(self):
"""删除商品原价这个属性"""
del self.__price PRICE = property(get_price, set_price, del_price, "价格属性描述...") obj = Goods() ret = obj.PRICE # 自动调用第一个参数中定义的方法:get_name
print(ret) # 80.0
obj.PRICE = 200 # 自动调用第二个参数中定义的方法:set_name,并将"200"当作参数传入
print(obj.PRICE ) # 160.0
del obj.PRICE # 自动调用第三个参数中定义的方法:del_name

注意:Python Web框架 Django 的视图中,request.POST就是使用静态字段的方式创建属性。

class WSGIRequest(http.HttpRequest):
def __init__(self, environ):
script_name = get_script_name(environ)
path_info = get_path_info(environ)
if not path_info:
# Sometimes PATH_INFO exists, but is empty (e.g. accessing
# the SCRIPT_NAME URL without a trailing slash). We really need to
# operate as if they'd requested '/'. Not amazingly nice to force
# the path like this, but should be harmless.
path_info = '/'
self.environ = environ
self.path_info = path_info
self.path = '%s/%s' % (script_name.rstrip('/'), path_info.lstrip('/'))
self.META = environ
self.META['PATH_INFO'] = path_info
self.META['SCRIPT_NAME'] = script_name
self.method = environ['REQUEST_METHOD'].upper()
_, content_params = cgi.parse_header(environ.get('CONTENT_TYPE', ''))
if 'charset' in content_params:
try:
codecs.lookup(content_params['charset'])
except LookupError:
pass
else:
self.encoding = content_params['charset']
self._post_parse_error = False
try:
content_length = int(environ.get('CONTENT_LENGTH'))
except (ValueError, TypeError):
content_length = 0
self._stream = LimitedStream(self.environ['wsgi.input'], content_length)
self._read_started = False
self.resolver_match = None def _get_scheme(self):
return self.environ.get('wsgi.url_scheme') def _get_request(self):
warnings.warn('`request.REQUEST` is deprecated, use `request.GET` or '
'`request.POST` instead.', RemovedInDjango19Warning, 2)
if not hasattr(self, '_request'):
self._request = datastructures.MergeDict(self.POST, self.GET)
return self._request @cached_property
def GET(self):
# The WSGI spec says 'QUERY_STRING' may be absent.
raw_query_string = get_bytes_from_wsgi(self.environ, 'QUERY_STRING', '')
return http.QueryDict(raw_query_string, encoding=self._encoding) ############### Look Here ###############
def _get_post(self):
if not hasattr(self, '_post'):
self._load_post_and_files()
return self._post ############### Look Here ###############
def _set_post(self, post):
self._post = post @cached_property
def COOKIES(self):
raw_cookie = get_str_from_wsgi(self.environ, 'HTTP_COOKIE', '')
return http.parse_cookie(raw_cookie) def _get_files(self):
if not hasattr(self, '_files'):
self._load_post_and_files()
return self._files ############### Look Here ###############
POST = property(_get_post, _set_post)
FILES = property(_get_files)
REQUEST = property(_get_request)

Django源码

面向对象:classmethod、staticmethod、property的更多相关文章

  1. Python类中装饰器classmethod,staticmethod,property,

    @classmethod 有的时候在类中会有一种情况,就是这个方法并不需要使用每一个对象属性 因此 这个方法中的self参数一个完全无用的参数,使用classmethod class A: __cou ...

  2. python面试题之下面这些是什么意思:@classmethod, @staticmethod, @property?

    回答背景知识 这些都是装饰器(decorator).装饰器是一种特殊的函数,要么接受函数作为输入参数,并返回一个函数,要么接受一个类作为输入参数,并返回一个类. @标记是语法糖(syntactic s ...

  3. 初识面向对象(钻石继承,super,多态,封装,method,property,classmethod,staticmethod)

    组合 什么有什么的关系 一个类的对象作为另一个类的对象继承 子类可以使用父类中的名字(静态属性 方法)抽象类和接口类 只能不继承,不能被实例化 子类必须实现父类中的同名方法———规范代码 metacl ...

  4. 初识面向对象-封装、property装饰器、staticmathod(静态的方法)、classmethod(类方法) (五)

    封装 # class Room:# def __init__(self,name,length,width):# self.__name = name# self.__length = length# ...

  5. @classmethod @staticmethod 个人理解

    官方解释 @classmethod 一个类方法把类自己作为第一个实参, 就像一个实例方法把实例自己作为第一个实参. 语法格式: class C: @classmethod def f(cls, arg ...

  6. 面向对象 公有私有 property classmethod staticmethod

    接口类(抽象类)--------就是一种规范 面向对象的私有与公有 对于每一个类的成员而言都有两种形式: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能方法 私有成员和公有成员的访问限制不 ...

  7. python 全栈开发,Day22(封装,property,classmethod,staticmethod)

    一.封装 封装 : 广义上的 :把一堆东西装在一个容器里 狭义上的 :会对一种现象起一个专门属于它的名字 函数和属性装到了一个非全局的命名空间 —— 封装 隐藏对象的属性和实现细节,仅对外提供公共访问 ...

  8. @classmethod, @staticmethod和@property这三个装饰器的使用对象是在类中定义的函数。下面的例子展示了它们的用法和行为:

    class MyClass(object): def __init__(self): self._some_property = "properties are nice" sel ...

  9. python 之 staticmethod,classmethod,property的区别

    绑定方法和非绑定方法: 普通def定义的都是绑定给对象的方法,对象调用时会自动传入对象本事,而类调用时需手动传入对象. 加上@classmethod装饰器就是绑定给类的方法,会自动传类本身 加上@st ...

  10. Python学习第十六课——静态属性(property, classmethod, staticmethod)

    计算所居住房子的面积 普通写法 class Room: def __init__(self,name,owner,width,length,heigh): self.name=name self.ow ...

随机推荐

  1. zedboard 流水灯

    #include"xparameters.h"/* Peripheral parameters 外围的參数 */ #include"xgpio.h"/* GPI ...

  2. linux下误删数据文件恢复

    linux下文件被删除能够用非常多工具进行恢复.比如undelete(适合ext2,ext3).giis(不能恢复安装giis之前的文件).ext3grep(仅限ext3).R-linux(支持ext ...

  3. 双logo

    from aip import AipSpeech bd_k_l = ['11059852', '5Kk01GtG2fjCwpzEkwdn0mjw', 'bp6Wyx377Elq7RsCQZzTBgG ...

  4. c++中读写文件操作

    读写文件这个,不常用,每次用的时候都会百度一下,每次写法还都不一样,所有总是记混.今天利用点时间总结下之前工程中用过的.以后就安照这种方法写了. 搞acmicpc的时候喜欢用freopen(),这个是 ...

  5. Android CountDownTimer的使用

    官方提供的用法如下: new CountDownTimer(30000, 1000) { public void onTick(long millisUntilFinished) { mTextFie ...

  6. cf 749D Leaving Auction

    Leaving Auction time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  7. ajax接收处理json格式数据

    ajax在前后端的交互中应用非常广泛,通过请求后台接口接收处理json格式数据展现在前端页面. 下面我们来简单用 ajax在本地做一个接收并处理json的小例子 首先我们要新建一个叫做data的jso ...

  8. 使用php实现二叉搜索树

    看到一位大神写的js的搜索树,自己也按照模式写了一个php的二叉搜索树. <?phpclass node{ public $data; public $key; public $left=nul ...

  9. codeforces——模拟

    805 B. 3-palindrome    http://codeforces.com/problemset/problem/805/B /* 题意字符串中不能有长度为三的回文串,且c数量最少 */ ...

  10. 如何获取<a>标签的Id

    案例: <a id='213' href='javascript:void(0);'onclick=DealFun(this.Id);>删除</a> 解决方案: functio ...