zoukankan      html  css  js  c++  java
  • 面向对象: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源码
  • 相关阅读:
    漫谈iOS程序的证书和签名机制
    (转) Xcode 7 Bitcode
    iOS: How To Make AutoLayout Work On A ScrollView
    Objective C运行时(runtime)
    如何让iOS 保持界面流畅?这些技巧你知道吗
    iPhone 6 屏幕揭秘
    用HTML和CSS实现WWDC 2015上的动画效果
    桌球歷史:削球、快攻、弧圈球
    [WPF 自定义控件]自定义控件库系列文章
    UWP 自定义控件:了解模板化控件 系列文章
  • 原文地址:https://www.cnblogs.com/believepd/p/10404371.html
Copyright © 2011-2022 走看看