一、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. 分布式数据库中间件DDM的实现原理

    随着数据量不断增大,传统的架构模式难以解决业务量不断增长所带来的问题,特别是在业务成线性.甚至指数级上升的情况.此时我们不得不通过水平扩展,把数据库放到不同服务器上来解决问题,也就是我们说的数据库中间 ...

  2. Android数据存储之IO

    Android开发中免不了数据本地的存储,今天我们来说一说怎样利用IO流来进行数据存储. 这里我们通过模拟一个QQ登陆界面的小demo来实际操作IO流. 功能描写叙述:点击button能够保存用户输入 ...

  3. Spring MVC学习-------------訪问到静态的文件

    怎样訪问到静态的文件,如jpg,js,css? 怎样你的DispatcherServlet拦截"*.do"这种有后缀的URL.就不存在訪问不到静态资源的问题. 假设你的Dispat ...

  4. cojs1101. [Vijos1369] 难解的问题==codevs 2188 最长上升子序列

    [题目描述] 在你的帮助下,蔚蓝来到了埃及.在金字塔里,蔚蓝看到了一个问题,传说,能回答出这个问题的人就能受到埃及法老的祝福,可是蔚蓝日夜奋战,还是想不出来,你能帮帮他么?(XXX: 胡扯,教主怎么可 ...

  5. POJ 2610:Dog & Gopher

    Dog & Gopher Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 4142   Accepted: 1747 ...

  6. YTU 2782: 用数字造数字

    2782: 用数字造数字 时间限制: 1 Sec  内存限制: 128 MB 提交: 191  解决: 160 题目描述 输入一个3位以上的整数,求其中最大的数字最小的数字之间的差.例如:输入8729 ...

  7. SQL SERVER 语句大全

    ·SQL的简单查询实例教程关键词:SQL语句大全 中文网 整理编辑,经典SQL语句大全(SQL语句大总结),欢迎网友投稿 下列语句部分是Mssql语句,不可以在access中使用.SQL分类:DDL— ...

  8. openstack 杂记 备忘

  9. java普通代码块、静态代码块、默认构造方法的执行顺序

    package test; class Parent{ { System.out.println("父类普通代码块"); } static{ System.out.println( ...

  10. bzoj2427:[HAOI2010]软件安装(Tarjan+tree_dp)

    2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1053  Solved: 424[Submit][Statu ...