当前位置: 首页 > news >正文

面向对象: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'
View Code

静态字段方式:在类中定义值为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源码

 

转载于:https://www.cnblogs.com/believepd/p/10404371.html

相关文章:

  • 面试宝典系列-nginx的缓冲和缓存
  • GitHub:我们为什么会弃用jQuery?
  • PostgrepSQL(大象)的使用
  • 如何在Ubuntu14.04中创建Python虚拟环境
  • Java日志系统(上)
  • BCH社区意见分歧:引领市场VS迎合市场?
  • 063_Apex 的 Test类说明
  • 前后端分离产生的跨域问题的解决方案之--jsonp、nginx代理、设置头信息等
  • 开篇:Pyhon基础笔记
  • 外国人又玩出新花样,仅需几行CSS代码就能让iPhone重启、Mac卡顿
  • SaaS技术栈的走势
  • 502错误,让你进一步明白nginx和php-fpm之间的关系
  • Oracle数据库-备份整个数据库与还原整个数据库数据
  • JVM:带你查看常见的问题,以及分析处方法
  • Mozilla开发全新的公开网络API WebXR 来实现增强现实
  • [Vue CLI 3] 配置解析之 css.extract
  • Apache Spark Streaming 使用实例
  • Computed property XXX was assigned to but it has no setter
  • JavaScript函数式编程(一)
  • Kibana配置logstash,报表一体化
  • Sass 快速入门教程
  • scrapy学习之路4(itemloder的使用)
  • Spark RDD学习: aggregate函数
  • 阿里云Kubernetes容器服务上体验Knative
  • 和 || 运算
  • 猴子数据域名防封接口降低小说被封的风险
  • 机器学习 vs. 深度学习
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 问:在指定的JSON数据中(最外层是数组)根据指定条件拿到匹配到的结果
  • 想写好前端,先练好内功
  • 小程序开发中的那些坑
  • 《天龙八部3D》Unity技术方案揭秘
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • Redis4.x新特性 -- 萌萌的MEMORY DOCTOR
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 新年再起“裁员潮”,“钢铁侠”马斯克要一举裁掉SpaceX 600余名员工 ...
  • ​卜东波研究员:高观点下的少儿计算思维
  • #if 1...#endif
  • #NOIP 2014# day.1 T2 联合权值
  • #pragma once与条件编译
  • #微信小程序:微信小程序常见的配置传值
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (Python) SOAP Web Service (HTTP POST)
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (附源码)计算机毕业设计ssm本地美食推荐平台
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (算法二)滑动窗口
  • (转) ns2/nam与nam实现相关的文件
  • (转)从零实现3D图像引擎:(8)参数化直线与3D平面函数库
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .Net 路由处理厉害了