面向对象:classmethod、staticmethod、property
一、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的更多相关文章
- Python类中装饰器classmethod,staticmethod,property,
@classmethod 有的时候在类中会有一种情况,就是这个方法并不需要使用每一个对象属性 因此 这个方法中的self参数一个完全无用的参数,使用classmethod class A: __cou ...
- python面试题之下面这些是什么意思:@classmethod, @staticmethod, @property?
回答背景知识 这些都是装饰器(decorator).装饰器是一种特殊的函数,要么接受函数作为输入参数,并返回一个函数,要么接受一个类作为输入参数,并返回一个类. @标记是语法糖(syntactic s ...
- 初识面向对象(钻石继承,super,多态,封装,method,property,classmethod,staticmethod)
组合 什么有什么的关系 一个类的对象作为另一个类的对象继承 子类可以使用父类中的名字(静态属性 方法)抽象类和接口类 只能不继承,不能被实例化 子类必须实现父类中的同名方法———规范代码 metacl ...
- 初识面向对象-封装、property装饰器、staticmathod(静态的方法)、classmethod(类方法) (五)
封装 # class Room:# def __init__(self,name,length,width):# self.__name = name# self.__length = length# ...
- @classmethod @staticmethod 个人理解
官方解释 @classmethod 一个类方法把类自己作为第一个实参, 就像一个实例方法把实例自己作为第一个实参. 语法格式: class C: @classmethod def f(cls, arg ...
- 面向对象 公有私有 property classmethod staticmethod
接口类(抽象类)--------就是一种规范 面向对象的私有与公有 对于每一个类的成员而言都有两种形式: 公有成员,在任何地方都能访问 私有成员,只有在类的内部才能方法 私有成员和公有成员的访问限制不 ...
- python 全栈开发,Day22(封装,property,classmethod,staticmethod)
一.封装 封装 : 广义上的 :把一堆东西装在一个容器里 狭义上的 :会对一种现象起一个专门属于它的名字 函数和属性装到了一个非全局的命名空间 —— 封装 隐藏对象的属性和实现细节,仅对外提供公共访问 ...
- @classmethod, @staticmethod和@property这三个装饰器的使用对象是在类中定义的函数。下面的例子展示了它们的用法和行为:
class MyClass(object): def __init__(self): self._some_property = "properties are nice" sel ...
- python 之 staticmethod,classmethod,property的区别
绑定方法和非绑定方法: 普通def定义的都是绑定给对象的方法,对象调用时会自动传入对象本事,而类调用时需手动传入对象. 加上@classmethod装饰器就是绑定给类的方法,会自动传类本身 加上@st ...
- Python学习第十六课——静态属性(property, classmethod, staticmethod)
计算所居住房子的面积 普通写法 class Room: def __init__(self,name,owner,width,length,heigh): self.name=name self.ow ...
随机推荐
- 分布式消息服务DMS与开源Kafka对比
分布式消息服务(简称DMS)是一项基于高可用分布式集群技术的消息中间件服务,提供了可靠且可扩展的托管消息队列,用于收发消息和存储消息.那么,比起自建开源的Kafka,分布式消息服务DMS有哪些好处呢? ...
- Android之实现ViewPager+Fragment左右滑动
近期看新闻发现新闻的页面是能够左右滑动的.于是自己就好奇起来了,之前做过ViewPager展示图片,在想怎么载入页面呢?研究了一下.发现就是加入了Fragment,废话不多说,揭秘奥秘的时候到了. 使 ...
- ssh连接超时问题解决方案,每一种方案都可以
1.服务端修改 vim /etc/ssh/sshd_config 修改 ClientAliveInterval 60 ClientAliveCountMax 40 60秒,向客户端发送一次请求. 超过 ...
- iOS-获取子视图父控制器
开发中有的时候需要涉及当前视图的父级视图,可以通过UIResponder来获取,有两种实现方式: UIView *next=sender; while ([next superview]) { nex ...
- web跨域问题回顾
晚上看spring web源码时看到了cors包,查了一下原来是在4.2之后新加的用来更方便让web应用服务支持cors协议的.于是有了下面几个问题. web跨域问题的起源是因为浏览器为了安全而遵循的 ...
- Tool:安全狗
ylbtech-Tool:安全狗 安全狗,互联网安全品牌,云安全服务与解决方案提供商 .企业用户遍布互联网金融.电商.游戏.移动互联网.政府单位等多个行业. 1.返回顶部 1. 2. 2.返回顶部 ...
- bzoj1061&&bzoj3256
http://www.lydsy.com/JudgeOnline/problem.php?id=1061 单纯形... 先开始我不知道对偶,看着代码不知所措,并不能懂他们写的是什么... 单纯形的标准 ...
- Linux 命令多到记不住?这个开源项目帮你一网打尽!
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 最近发现了一个 ...
- leetCode----day02---- 买卖股票的最佳时机 II
要求: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能同时参与多笔交易(你必 ...
- 知识记忆1:标志寄存器PSW
8086CPU的flag寄存器结构如下: [ ] [ ] [ ] [ ] [OF][DF][IF][TF][SF][ZF][ ][AF][ ][PF][ ][CF] 其中debug中的显示为: 标志 ...