精华内容
下载资源
问答
  • 例如,在一个类中定义了类属性 __metaclass__,这就说明这个类使用了元类来创建。 那元类的实现原理究竟是怎样的?使用元类能帮我们在开发中解决什么样的问题? 这篇文章,我们就来看一下 Python 元类的来龙去脉。 ...

    如果你看过比较优秀的 Python 开源框架,肯定见到过元类的身影。例如,在一个类中定义了类属性 __metaclass__,这就说明这个类使用了元类来创建。

    那元类的实现原理究竟是怎样的?使用元类能帮我们在开发中解决什么样的问题?

    这篇文章,我们就来看一下 Python 元类的来龙去脉。

    什么是元类?

    我们都知道,定义一个类,然后调用它的构造方法,就可以初始化出一个实例出来,就像下面这样:

    class Person(object)  
        def __init__(name):  
            self.name = name  
    p = Person('zhangsan') 
    

    那你有没有想过,我们平时定义的类,它是如何创建出来的?

    别着急,我们先来看一个例子:

    >>> a = 1               # 创建a的类是int a是int的实例  
    >>> a.__class__  
    <type 'int'>  
    >>> b = 'abc'           # 创建b的类是str b是str的实例  
    >>> b.__class__  
    <type 'str'>  
    >>> def c():            # 创建c的类是function 方法c是function的实例  
    ...     pass  
    >>> c.__class__  
    <type 'function'>  
    >>> class D(object):    # 创建d的类是D d是D的实例  
    ...     pass  
    >>> d.__class__  
    <class '__main__.D'> 
    

    在这个例子中,我们定义了int、str、function、class,然后分别调用了它们的__class__方法,这个 __class__ 方法可以返回实例是如何创建出来的。

    从方法返回的结果我们可以看到:

    • 创建整数 a 的类是 int,也就是说 a 是 int 的一个实例
    • 创建字符串 b 的类是 str,也就是说 b 是 str 的一个实例
    • 创建函数 c 的类是 function,也就是说 c 是 function 的一个实例
    • 创建实例 d 的类是 class,也就是说 d 是 class 的一个实例

    除了这些之外,我们在开发中使用到的例如 list、dict 也类似,你可以测试观察一下结果。

    现在我们已经得知,创建这些实例的类是 int、str、function、class,那进一步思考一下,这些类又是怎么创建出来的呢?

    同样地,我们也调用这些类的 __class__方法,观察结果:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    >>> a = 1 
    >>> a.__class__.__class__  
    <type 'type'>  
    >>>  
    >>> b = 'abc'  
    >>> b.__class__.__class__  
    <type 'type'>  
    >>>  
    >>> def c():  
    ...     pass  
    >>> c.__class__.__class__ 
    <type 'type'>  
    >>>  
    >>> class D(object):  
    ...     pass  
    >>> d = D()  
    >>> d.__class__.__class__  
    <type 'type'> 
    

    从结果我们可以看到,创建这些类的类,都是 type,所以 type 就是创建所有类的「元类」。也就是说,元类的作用就是用来创建类的。

    你可以这样理解:

    • 元类 -> 类
    • 类 -> 实例

    用伪代码表示,就是下面这样:

    klass = MetaClass()     # 元类创建类  
    obj = klass()           # 类创建实例 
    

    是不是很有意思?

    在这里,你也可以感受一下这句话的含义:Python 中一切皆对象!

    无论是普通类型、方法、实例,还是类,都可以统一看作对象,它们的起源就是元类。

    其实,在 Python 中,使用 type 方法,我们可就以创建出一个类,type 方法的语法如下:

    type(class_name, (base_class, ...), {attr_key: attr_value, ...}) 
    

    例如,像下面这样,我们使用 type 方法创建 MyClass 类,并且让它继承 object:

    >>> A = type('MyClass', (object, ), {}) # type创建一个类,继承object  
    >>> A  
    <class '__main__.MyClass'>  
    >>> A()  
    <__main__.MyClass object at 0x10d905950> 
    

    我们还可以使用 type 创建一个包含属性和方法的类:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    >>> def foo(self):  
    ...     return 'foo'  
    ...  
    >>> name = 'zhangsan'  
    >>>  
    # type 创建类B 继承object 包含 name 属性和 foo 方法  
    >>> B = type('MyClass', (object, ), {'name': name, 'foo': foo})   
    >>> B.name          # 打印 name 属性  
    'zhangsan'  
    >>> print B().foo() # 调用 foo 方法  
    foo 
    

    通过 type 方法创建的类,和我们自己定义一个类,在使用上没有任何区别。

    其实,除了使用 type 方法创建一个类之外,我们还可以使用类属性 __metaclass__创建一个类,这就是下面要讲的「自定义元类」。

    自定义元类

    我们可以使用类属性__metaclass__把一个类的创建过程,转交给其它地方,可以像下面这样写:

    class A(object):  
        __metaclass__ = ... # 这个类的创建转交给其他地方  
        pass 
    

    这个例子中,我们先定义了类 A,然后定义了一个类属性__metaclass__,这个属性表示创建类 A 的过程,转交给其它地方处理。

    那么,这个类属性 __metaclass__需要怎么写呢?

    其实,它可以是一个方法,也可以是一个类。

    用方法创建类

    如果类属性 __metaclass__赋值的是一个方法,那么创建类的过程,就交给了一个方法来执行。

    def create_class(name, bases, attr):  
        print 'create class by method...'  
        # 什么事都没做 直接用type创建了一个类  
        return type(name, bases, attr)  
    class A(object):  
        # 创建类的过程交给了一个方法  
        __metaclass__ = create_class  
    # Output:      
    # create class by method ... 
    

    我们定义了create_class方法,然后赋值给__metaclass__,那么类 A 被创建时,就会调用 create_class方法。

    create_class方法中的逻辑,就是我们上面所讲到的,使用 type 方法创建出一个类,然后返回。

    用类创建类

    明白了用方法创建类之后,我们来看一下用类来创建另一个类。

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    class B(type):  
        # 必须定义 __new__ 方法 返回一个类  
        def __new__(cls, name, bases, attr):  
            print 'create class by B ...'  
            return type(name, bases, attr)  
    class A(object):  
        # 创建类的过程交给了B  
        __metaclass__ = B   
     # Output:  
    # create class by B ... 
    

    在这个例子中,我们定义了类 B,然后把它赋值给了 A 的类变量 __metaclass__,这就表示创建 A 的过程,交给了类 B。

    B 在定义时,首先继承了 type,然后定义了__new__方法,最后调用 type 方法返回了一个类,这样当创建类 A 时,会自动调用类 B 的__new__方法,然后得到一个类实例。

    创建类的过程

    好了,上面我们演示了通过元类创建一个类的两种方式,分别是通过方法创建和通过类创建。

    其实创建一个类的完整流程如下:

    • 检查类中是否有 __metaclass__ 属性,如果有,则调用 __metaclass__ 指定的方法或类创建
    • 如果类中没有 __metaclass__ 属性,那么会继续在父类中寻找
    • 如果任何父类中都没有,那么就用 type 创建这个类

    也就是说,如果我们没有指定 __metaclass__,那么所有的类都是默认由 type 创建,这种情况是我们大多数定义类时的流程。

    如果类中指定了 __metaclass__,那么这个类的创建就会交给外部来做,外部可以定义具体的创建逻辑。

    哪种创建类的方式更好?

    虽然有两种方式可以创建类,那么哪种方式更好呢?

    一般我们建议使用类的方式创建,它的优点如下:

    • 使用类更能清楚地表达意图
    • 使用类更加 OOP,因为类可以继承其他类,而且可以更友好地使用面向对象特性
    • 使用类可以更好地组织代码结构

    另外,使用类创建一个类时,这里有一个优化点:在__new__方法中不建议直接调用 type 方法,而是建议调用 super 的__new__ 来创建类,执行结果与 type 方法是一样的:

    class B(type):  
        def __new__(cls, name, bases, attr):  
            # 使用 super.__new__ 创建类  
            return super(B, cls).__new__(cls, name, bases, attr)     
    

    创建类时自定义行为

    前面我们用元类创建一个类时,它的功能非常简单。现在我们来看一下,使用元类创建类时,如何定义一些自己的逻辑,然后改变类的属性或行为。

    我们看下面这个例子:

    '''
    遇到问题没人解答?小编创建了一个Python学习交流QQ群:531509025
    寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
    '''
    # coding: utf8  
    class Meta(type):  
        def __new__(cls, name, bases, attr):  
            # 通过 Meta 创建的类 属性会都变成大写  
            for k, v in attr.items():  
                if not k.startswith('__'):  
                    attr[k] = v.upper()  
                else:  
                    attr[k] = v  
            return type(name, bases, attr)  
    class A(object):  
        # 通过 Meta 创建类  
        __metaclass__ = Meta  
        name = 'zhangsan'  
    class B(object):  
        # 通过 Meta 创建类  
        __metaclass__ = Meta   
        name = 'lisi'  
    # 打印类属性 会自动变成大写  
    print A.name    # ZHANGSAN  
    print B.name    # LISI 
    

    在这个例子中,我们定义了一个元类 Meta,然后在定义类 A 和 B 时,把创建类的过程交给了 Meta,在 Meta 类中,我们可以拿到 A 和 B 的属性,然后把它们的属性都转换成了大写。

    所以当我们打印 A 和 B 的属性时,虽然定义的变量是小写的,但输出结果都变成了大写,这就是元类发挥的作用。

    使用场景

    了解了元类的实现原理,那么元类都会用在哪些场景呢?

    我们在开发中其实用的并不多,元类的使用,经常会出现在一些框架中,例如Django ORM、peewee,下面是使用 Django ORM 定义一个数据表映射类的代码:

    class Person(models.Model):  
        # 注意: name 和 age 是类属性  
        name = models.CharField(max_length=30)  
        age = models.IntegerField()      
    person = Person(name='zhangsan', age=20)  
    print person.name   # zhangsan  
    print person.age    # 20 
    

    仔细看在这段代码中,我们定义了一个 Person 类,然后在类中定义了类属性 name 和 age,它们的类型分别是 CharField 和 IntegerField,之后我们初始化 Person 实例,然后通过实例获取 name 和 age 属性,输出的却是 str 和 int,而不再是 CharField 和 IntegerField。

    能做到这样的秘密就在于,Person 类在创建时,它的逻辑交给了另一个类,这个类针对类属性进行了转换,最终变成对象与数据表的映射,通过转换映射,我们就可以通过实例属性的方式,友好地访问表中对应的字段值了。

    总结

    总结一下,这篇文章我们讲了元类的实现原理,了解到元类是创建所有类的根源,我们可以通过 type 方法,或者在类中定义__metaclass__ 的方式,把创建类的过程交给外部。

    当使用 __metaclass__ 创建类时,它可以是一个方法,也可以是一个类。我们通常会使用类的方式去实现一个元类,这样做更方便我们组织代码,实现面向对象。

    在使用元类创建一个类时,我们可以修改创建类的细节,例如对属性做统一的转换,或者增加新的方法等等,这对于我们开发一个复杂功能的类很友好,它可以把创建类的细节屏蔽在元类中,所以元类常常用在优秀的开源框架中。、

    展开全文
  • 如果你看过比较优秀的 Python 开源框架,肯定见到过元类的身影。例如,在一个类中定义了类属性__metaclass__,这就说明这个类使用了元类来创建。那元类的实现原理究竟是怎样的?...

    如果你看过比较优秀的 Python 开源框架,肯定见到过元类的身影。例如,在一个类中定义了类属性 __metaclass__,这就说明这个类使用了元类来创建。

    那元类的实现原理究竟是怎样的?使用元类能帮我们在开发中解决什么样的问题?

    这篇文章,我们就来看一下 Python 元类的来龙去脉。

    什么是元类?

    我们都知道,定义一个类,然后调用它的构造方法,就可以初始化出一个实例出来,就像下面这样:

    class Person(object)
    
        def __init__(name):
            self.name = name
    
    p = Person('zhangsan')
    
    

    那你有没有想过,我们平时定义的类,它是如何创建出来的?

    别着急,我们先来看一个例子:

    >>> a = 1               # 创建a的类是int a是int的实例
    >>> a.__class__
    <type 'int'>
    
    >>> b = 'abc'           # 创建b的类是str b是str的实例
    >>> b.__class__
    <type 'str'>
    
    >>> def c():            # 创建c的类是function 方法c是function的实例
    ...     pass
    >>> c.__class__
    <type 'function'>
    
    >>> class D(object):    # 创建d的类是D d是D的实例
    ...     pass
    >>> d.__class__
    <class '__main__.D'>
    
    

    在这个例子中,我们定义了 intstrfunctionclass,然后分别调用了它们的__class__ 方法,这个 __class__ 方法可以返回实例是如何创建出来的。

    从方法返回的结果我们可以看到:

    • 创建整数 a 的类是 int,也就是说 a 是 int 的一个实例

    • 创建字符串 b 的类是 str,也就是说 b 是 str 的一个实例

    • 创建函数 c 的类是 function,也就是说 c 是 function 的一个实例

    • 创建实例 d 的类是 class,也就是说 d 是 class 的一个实例

    除了这些之外,我们在开发中使用到的例如 listdict 也类似,你可以测试观察一下结果。

    现在我们已经得知,创建这些实例的类是 intstrfunctionclass,那进一步思考一下,这些类又是怎么创建出来的呢?

    同样地,我们也调用这些类的 __class__ 方法,观察结果:

    >>> a = 1
    >>> a.__class__.__class__
    <type 'type'>
    >>>
    >>> b = 'abc'
    >>> b.__class__.__class__
    <type 'type'>
    >>>
    >>> def c():
    ...     pass
    >>> c.__class__.__class__
    <type 'type'>
    >>>
    >>> class D(object):
    ...     pass
    >>> d = D()
    >>> d.__class__.__class__
    <type 'type'>
    
    

    从结果我们可以看到,创建这些类的类,都是 type,所以 type 就是创建所有类的「元类」。也就是说,元类的作用就是用来创建类的

    你可以这样理解:

    1. 元类 -> 类

    2. 类 -> 实例

    用伪代码表示,就是下面这样:

    klass = MetaClass()     # 元类创建类
    obj = klass()           # 类创建实例
    
    

    是不是很有意思?

    在这里,你也可以感受一下这句话的含义:Python 中一切皆对象!

    无论是普通类型、方法、实例,还是类,都可以统一看作对象,它们的起源就是元类。

    其实,在 Python 中,使用 type 方法,我们可就以创建出一个类,type 方法的语法如下:

    type(class_name, (base_class, ...), {attr_key: attr_value, ...})
    
    

    例如,像下面这样,我们使用 type 方法创建 MyClass 类,并且让它继承 object

    >>> A = type('MyClass', (object, ), {}) # type创建一个类,继承object
    >>> A
    <class '__main__.MyClass'>
    >>> A()
    <__main__.MyClass object at 0x10d905950>
    
    

    我们还可以使用 type 创建一个包含属性和方法的类:

    >>> def foo(self):
    ...     return 'foo'
    ...
    >>> name = 'zhangsan'
    >>>
    # type 创建类B 继承object 包含 name 属性和 foo 方法
    >>> B = type('MyClass', (object, ), {'name': name, 'foo': foo}) 
    >>> B.name          # 打印 name 属性
    'zhangsan'
    >>> print B().foo() # 调用 foo 方法
    foo
    
    

    通过 type 方法创建的类,和我们自己定义一个类,在使用上没有任何区别。

    其实,除了使用 type 方法创建一个类之外,我们还可以使用类属性 __metaclass__ 创建一个类,这就是下面要讲的「自定义元类」。

    自定义元类

    我们可以使用类属性 __metaclass__ 把一个类的创建过程,转交给其它地方,可以像下面这样写:

    class A(object):
        __metaclass__ = ... # 这个类的创建转交给其他地方
        pass
    
    

    这个例子中,我们先定义了类 A,然后定义了一个类属性 __metaclass__,这个属性表示创建类 A 的过程,转交给其它地方处理。

    那么,这个类属性 __metaclass__ 需要怎么写呢?

    其实,它可以是一个方法,也可以是一个类。

    用方法创建类

    如果类属性 __metaclass__ 赋值的是一个方法,那么创建类的过程,就交给了一个方法来执行。

    def create_class(name, bases, attr):
        print 'create class by method...'
        # 什么事都没做 直接用type创建了一个类
        return type(name, bases, attr)
    
    class A(object):
        # 创建类的过程交给了一个方法
        __metaclass__ = create_class
    
    # Output:    
    # create class by method ...
    
    

    我们定义了 create_class 方法,然后赋值给 __metaclass__,那么类 A 被创建时,就会调用 create_class 方法。

    而 create_class 方法中的逻辑,就是我们上面所讲到的,使用 type 方法创建出一个类,然后返回。

    用类创建类

    明白了用方法创建类之后,我们来看一下用类来创建另一个类。

    class B(type):
        # 必须定义 __new__ 方法 返回一个类
        def __new__(cls, name, bases, attr):
            print 'create class by B ...'
            return type(name, bases, attr)
    
    class A(object):
        # 创建类的过程交给了B
        __metaclass__ = B
        
    # Output:
    # create class by B ...
    
    

    在这个例子中,我们定义了类 B,然后把它赋值给了 A 的类变量 __metaclass__,这就表示创建 A 的过程,交给了类 B。

    B 在定义时,首先继承了 type,然后定义了 __new__ 方法,最后调用 type 方法返回了一个类,这样当创建类 A 时,会自动调用类 B 的 __new__ 方法,然后得到一个类实例。

    创建类的过程

    好了,上面我们演示了通过元类创建一个类的两种方式,分别是通过方法创建和通过类创建。

    其实创建一个类的完整流程如下:

    1. 检查类中是否有 __metaclass__ 属性,如果有,则调用 __metaclass__ 指定的方法或类创建

    2. 如果类中没有 __metaclass__ 属性,那么会继续在父类中寻找

    3. 如果任何父类中都没有,那么就用 type 创建这个类

    也就是说,如果我们没有指定 __metaclass__,那么所有的类都是默认由 type 创建,这种情况是我们大多数定义类时的流程。

    如果类中指定了 __metaclass__,那么这个类的创建就会交给外部来做,外部可以定义具体的创建逻辑。

    哪种创建类的方式更好?

    虽然有两种方式可以创建类,那么哪种方式更好呢?

    一般我们建议使用类的方式创建,它的优点如下:

    • 使用类更能清楚地表达意图

    • 使用类更加 OOP,因为类可以继承其他类,而且可以更友好地使用面向对象特性

    • 使用类可以更好地组织代码结构

    另外,使用类创建一个类时,这里有一个优化点:在 __new__ 方法中不建议直接调用 type 方法,而是建议调用 super 的 __new__ 来创建类,执行结果与 type 方法是一样的:

    class B(type):
    
        def __new__(cls, name, bases, attr):
            # 使用 super.__new__ 创建类
            return super(B, cls).__new__(cls, name, bases, attr)    
    
    

    创建类时自定义行为

    前面我们用元类创建一个类时,它的功能非常简单。现在我们来看一下,使用元类创建类时,如何定义一些自己的逻辑,然后改变类的属性或行为。

    我们看下面这个例子:

    # coding: utf8
    
    class Meta(type):
        def __new__(cls, name, bases, attr):
            # 通过 Meta 创建的类 属性会都变成大写
            for k, v in attr.items():
                if not k.startswith('__'):
                    attr[k] = v.upper()
                else:
                    attr[k] = v
            return type(name, bases, attr)
    
    class A(object):
        # 通过 Meta 创建类
        __metaclass__ = Meta
    
        name = 'zhangsan'
    
    class B(object):
        # 通过 Meta 创建类
        __metaclass__ = Meta
    
        name = 'lisi'
    
    # 打印类属性 会自动变成大写
    print A.name    # ZHANGSAN
    print B.name    # LISI
    
    

    在这个例子中,我们定义了一个元类 Meta,然后在定义类 A 和 B 时,把创建类的过程交给了  Meta,在 Meta 类中,我们可以拿到 A 和 B 的属性,然后把它们的属性都转换成了大写。

    所以当我们打印 A 和 B 的属性时,虽然定义的变量是小写的,但输出结果都变成了大写,这就是元类发挥的作用。

    使用场景

    了解了元类的实现原理,那么元类都会用在哪些场景呢?

    我们在开发中其实用的并不多,元类的使用,经常会出现在一些框架中,例如Django ORMpeewee,下面是使用 Django ORM 定义一个数据表映射类的代码:

    class Person(models.Model):
        # 注意: name 和 age 是类属性
        name = models.CharField(max_length=30)
        age = models.IntegerField()
        
    person = Person(name='zhangsan', age=20)
    print person.name   # zhangsan
    print person.age    # 20
    
    

    仔细看在这段代码中,我们定义了一个 Person 类,然后在类中定义了类属性 name 和 age,它们的类型分别是 CharField 和 IntegerField,之后我们初始化 Person 实例,然后通过实例获取 name 和 age 属性,输出的却是 str 和 int,而不再是 CharField 和 IntegerField

    能做到这样的秘密就在于,Person 类在创建时,它的逻辑交给了另一个类,这个类针对类属性进行了转换,最终变成对象与数据表的映射,通过转换映射,我们就可以通过实例属性的方式,友好地访问表中对应的字段值了。

    总结

    总结一下,这篇文章我们讲了元类的实现原理,了解到元类是创建所有类的根源,我们可以通过 type 方法,或者在类中定义 __metaclass__ 的方式,把创建类的过程交给外部。

    当使用 __metaclass__ 创建类时,它可以是一个方法,也可以是一个类。我们通常会使用类的方式去实现一个元类,这样做更方便我们组织代码,实现面向对象。

    在使用元类创建一个类时,我们可以修改创建类的细节,例如对属性做统一的转换,或者增加新的方法等等,这对于我们开发一个复杂功能的类很友好,它可以把创建类的细节屏蔽在元类中,所以元类常常用在优秀的开源框架中。、

    更多阅读

    2020 年最佳流行 Python 库 Top 10

    2020 Python中文社区热门文章 Top 10

    5分钟快速掌握 Python 定时任务框架

    特别推荐


    点击下方阅读原文加入社区会员

    展开全文
  • 本节课,我们来学习,如何创建一个类, 也就是怎么python画设计方案 先来看一下 前面课程里出现过的 几张设计方案 前面女娲造人的故事里,女娲创造了6张设计方案 我们接下来根据那个故事的节奏,也来创造6张设计...

    文字有点长,对于不想看文字的朋友,可以去这里看视频,视频可能更好理解

    www.piqizhu.com/v/1GK0onadJ…

    本节课,我们来学习,如何创建一个类, 也就是怎么用python画设计方案

    先来看一下 前面课程里出现过的 几张设计方案

    前面女娲造人的故事里,女娲创造了6张设计方案

    我们接下来根据那个故事的节奏,也来创造6张设计方案

    创建类

    创建 物种设计图 的类

    先来看第一张设计方案, 物种设计方案

    这张设计图,里的东西,有四肢,还有个头、身体

    那么我们设计的类如下:

    class 物种设计方案:
        头 = 1
        前肢 = 2
        后肢 = 2
        身体 = 1
    复制代码

    要创建一个类, 和创建一个函数差不多,

    先写一个class,然后一个空格, 接着写类的名字,

    类的名字和变量名的命名规则一样,通常类名建议驼峰命名法

    也就是要像个骆驼

    比如, 你的类名是 man 那么应该写成 Man

    如果你的类名是 goodman 那么你应该写成 GoodMan

    每个单词的首字母用大写,如果只有一个字母,首字母要大写, 如果有多个单词,每个单词首字母都要大写

    这只是行业里的一个约定,并没有强制规定,你不遵守也可以

    我这里的例子,为了方便大家理解,会使用中文汉字

    class 后面的 物种设计方案 就是我的类名, 类名后面一个冒号

    接着换行,一个缩进,我这里给这个类,增加了4个属性,就像 声明变量一样

    同样为了便于大家理解,这里的变量名我也用了中文汉字

    这里的 物种设计方案 就是我们创建的类的名字,简称类名

    在类中的这几个变量,就是这个类的属性, 就和我们平时的变量是一样的,但这里的这几个变量,归属于这个类, 就好比,我们大家都归属于中国

    如此,我们就完成了, 物种设计方案的制作

    创建 动物设计方案 的类

    接下来,在这个基础上,制作一个动物设计方案

    class 动物设计方案(物种设计方案):
        def 吃东西(self):
            pass
        def(self):
        	pass
        def(self):
            pass
    复制代码

    你可以发现,这个类,和上个类十分相似,但也有一些区别,

    比如,类名后面多了个括号,括号里多了物种设计方案几个字,

    而且这个类里面,居然写了3个函数,这分别都是什么含义呢?

    类名后面的括号,写了谁,就表示这个类要继承谁, 我们这里的 动物设计方案, 继承了 物种设计方案,

    所以, 物种设计方案,被写在了, 动物设计方案后面的括号里, 这个括号,就是用来表示声明继承关系的

    这里我们可以看出 动物设计方案的 父类 就是 物种设计方案

    而 物种设计方案,在类名后面,直接就是问号,没有括号,他没有继承别人吗?

    其实是有的, 在Python内部, 某个类没有声明继承的话,Python会自动继承object类, 关于object类是什么, 我们以后会讲, 暂时你只要记住

    在Python里,所有类都是object类的后代

    那么类里面外面写的这3个函数是啥意思呢? 这3个函数就是类的方法, 通常我们叫做类方法,

    而且你应该也看到了, 类方法的第一个参数都是self,这个参数是必须要传的,不能少, 但这个参数名字你可以改成别的, 比如 你可以改成, a, 或者别的

    不过,为了便于大家理解, 行业里,大家统一都写的是self,所以,建议你也遵守这个规定

    这几个类函数,我们是留空的,写了个pass语句,没有填充内容,因为目前我们还不知道写什么好

    创建 人类设计方案 的类

    现在,让我们基于 人类设计方案,创造一个类吧

    class 人类设计方案(动物设计方案):
        type_name = "人"
        def 吃东西(self):
            print(self.type_name, ":开始用嘴巴吃东西")
        def(self):
            print(self.type_name, ":用", self.后肢 ,"条 后肢跑")
        def(self):
            print(self.type_name, ":啊啊啊")
    复制代码

    我们给这个类,添加了一个属性,type name, 值为 人

    并且,我们把从父类那里继承来的3个方法, 进行了重载,也就是把从父类那继承来的类方法里面的代码,进行了修改,写入了新的代码,这几个类方法,父类中就写了个pass,我们这里改成了print语句,这里面你可以写任何代码,就和函数没什么两样

    接着我们创建 狗类、猫类、鸭类

    class 狗类设计方案(动物设计方案):
        type_name = "狗"
        def 吃东西(self):
            print(self.type_name, ":开始用嘴巴吃东西")
        def(self):
            print(self.type_name, ":用", self.前肢+ self.后肢 ,"条腿 跑")
        def(self):
            print(self.type_name, ":汪汪汪")
    
    class 猫类设计方案(动物设计方案):
        type_name = "猫"
        def 吃东西(self):
            print("开始用嘴巴吃东西")
        def(self):
            print(self.type_name, ":用", self.前肢+ self.后肢 ,"条腿 跑")
        def(self):
            print("喵喵喵")
    
    class 鸭类设计方案(动物设计方案):
        type_name = "鸭"
        def 吃东西(self):
            print("开始用嘴巴吃东西")
        def(self):
            print(self.type_name, ":用",  self.后肢 ,"条 后肢 跑")
        def(self):
            print("嘎嘎嘎")
    复制代码

    你可以看到,我们给这几个类的类方法都填充了代码,

    你应该已经发现了, 每个类,都有一个 type_name 属性

    而且,在类方法中,都用到了type_name 这个属性,并且,前面还多出了一个 self.

    self. 这是什么意思呢? 这里的self 就代表 这个类自己

    比如,人类设计方案, 这个类中的self,就代表这个 [人类设计方案] ,我们这里 打印 self.type_name

    就表示 要打印, 人类设计方案 中的type_name,

    同样的道理, 在狗类设计方案中,打印 self.type_name ,就表示要访问 狗类设计方案 的 type_name属性

    self 就代表当时那种情景下的自己

    如果你还不理解不要紧,接下来的课程里,我们会详细的讲解

    转载于:https://juejin.im/post/5ccc5098e51d456e5977b21b

    展开全文
  • 编一个面向对象的程序来解决实际世界问题,首先要创建一个类,然后再用类来导引出实例。这就如同那个把“类”,比作制造实例产品工厂的比喻一样,你没有工厂,那工厂的一件一件产品何以产出?类就是创造实例的工厂,...

    标题尝试创建一个简单狗类程序——Python学习笔记九

    无穷的世界怎么去认知,然后执行?是先从个体和实例出发,还是从抽象的类出发?这个python语言,大概为这个问题提供了一种答案。编一个面向对象的程序来解决实际世界问题,首先要创建一个类,然后再用类来导引出实例。这就如同那个把“类”,比作制造实例产品工厂的比喻一样,你没有工厂,那工厂的一件一件产品何以产出?类就是创造实例的工厂,你得把工厂建起来,产品才有可能从母体中诞生。实在世界大概会有完全相反的答案,但python语言似乎只有从一般到特殊的路径,好像看不到有相反的路径。学习面向对象编程的知识,首先碰到的就是类,而学习类代码的编写基础,你首先要学习的,就是通过类来生成多个实例对象。本篇学习笔记,试图通过类与实例的生成编码,来理解python面向对象的编程程序到底有个什么样的基本步骤。

    标题一、编写和运行构造函数Animal.py

    全世界的生物种类繁多,除了植物还有动物,动物又可以继续下分,大概得几个层次才能下沉到哺乳动物中的猫类、牛类等。最和人类亲近的则是狗类,我模仿,也稍带点改良,在手册中学到的步骤,但首先不构造自身所在的人类,而是先构造和我们最亲近的狗类,然后导出狗类的实例,以纪念陪伴我们十多年的小狗圆圆,一只可爱而且漂亮的西施犬。

    构造之前得有以上简略设想,然后进入编码实现。在我所使用的atom的编辑器中,建构一个新文件,文件名就以Animal为名,一个小知识不能忘记,类名首字母得是大写。作为python的一个文件,文件名为:Animal.py。
    狗类作为动物的一个类别,与人类一样,具有众多属性。属性的一个积聚,是一个类别之所以成为其类别的区分标志。狗显然有数不清的属性,我取其四点:名称,颜色,国籍和价格。那个self参数大概是类别导引出实例的一个符号标志,在使用__init__初始化函数时,self几乎永远都是这个函数的第一参数。从这个意义上看,self就是一个编码所创建的类中,从类导引出的任意一个实例instance。
    Animal.py

    class Dog:
        def __init__(self, name, color, nation, sex):
            self.name = name
            self.color = color
            self.nation = nation
            self.price = price
    
    class Dog:
        def __init__(self, name, color, nation = None, price = 0):
            self.name = name
            self.color = color
            self.nation = nation
            self.price = price
    
    yuanyuan = Dog('Yuan Habagou', color = 'white')
    fangfang = Dog('Fang Muyangquan', color ='gold', price = 20000)
    print(yuanyuan.name, yuanyuan.color, yuanyuan.price)
    print(fangfang.name, fangfang.nation, fangfang.price)
    

    然后在交互式的window shell中执行和测试这个程序,得到如下结果。

    PS C:\Users\zzx21> cd py文件夹
    PS C:\Users\zzx21\py文件夹> python Animal.py
    Yuan Habagou white 0
    Fang Muyangquan None 20000
    PS C:\Users\zzx21\py文件夹>
    

    可以看到,这个编码文件,建立了一个狗类,导出狗类的两个实例,一个是yuanyuan,一个是fangfang。我们预先设定了它们的几个属性后,这些属性都可以通过函数的运行而显示出来。

    二、类函数可以不断地增加方法来强化程序功能

    以上的建构大约是最基本的,有了这个基本构架,程序可以不断地扩充,几乎可以随意添加任何函数在这个基本的类程序中。依然是模仿,我把animal.py的编码扩充,做成了另一个编码,文件名为animal1.py。这增加的函数,在类编码中称作方法,它让原来的函数有了一些新功能。所以python中的方法,也就是附加给类,并且旨在处理那些类实例的常规函数。
    Animal1.py

    class Dog:
        def __init__(self, name, color, nation, price):
            self.name = name
            self.color = color
            self.nation = nation
            self.price = price
    
    class Dog:
        def __init__(self, name, color, nation=None, price=0):
            self.name = name
            self.color = color
            self.nation = nation
            self.price = price
        def lastName(self):
            return self.name.split()[-1]
        def giveRaise(self, percent):
            self.price = int(self.price *(1 + percent))
    
    if __name__ == '__main__':
        yuanyuan = Dog('Yuan Habagou', color = 'white')
        fangfang = Dog('Fang Muyangquan', color = 'gold', price = 20000)
        print(yuanyuan.name, yuanyuan.price)
        print(fangfang.name, fangfang.price)
        print(yuanyuan.lastName(), fangfang.lastName())
        fangfang.giveRaise(.20)
        print(fangfang.price)
    

    在交互式编辑器中执行这个文件,得到如下结果:

    PS C:\Users\zzx21\py文件夹> python animal1.py
    Yuan Habagou 0
    Fang Muyangquan 20000
    Habagou Muyangquan
    24000
    PS C:\Users\zzx21\py文件夹>
    
    

    显然,给出了分离后的名称,给出在前的价格,和后来使用计算函数而获得的新价格。这个文件就比原先的文件,扩充了一些新功能,这些功能是用给出的方法而获得的。

    三、理解运算符重载

    运算符的重载我一直都不是很清楚它的含义,这个稍作更改的类程序让我对这个重载有了点认知。如果我在类对象下的函数或者方法中增加一个repr方法,在if循环中不是打印其中某个属性,而是打印某个名称下的全部属性,那么,那个实例就以一个整体的形式在交互式中被执行。我还是先拿出这个程序,得出结果后再来点解释吧。
    Animal2.py

    class Dog:
        def __init__(self, name, color, nation=None, price=0):
            self.name = name
            self.color = color
            self.nation = nation
            self.price = price
        def lastName(self):
            return self.name.split()[-1]
        def giveRaise(self, percent):
            self.pay = int(self.price *(1 + percent))
        def __repr__(self):
            return '[Dog: %s, %s]' % (self.name, self.price)
    
    if __name__ == '__main__':
        yuanyuan = Dog('Yuan Habagou', color = 'white')
        fangfang = Dog('Fang Muyangquan', color = 'gold', price = 20000)
        print(yuanyuan)
        print(fangfang)
        print(yuanyuan.lastName(), fangfang.lastName())
        fangfang.giveRaise(.20)
        print(fangfang)
    
    

    执行这个文件的结果:

    PS C:\Users\zzx21\py文件夹> python animal2.py
    [Dog: Yuan Habagou, 0]
    [Dog: Fang Muyangquan, 20000]
    Habagou Muyangquan
    [Dog: Fang Muyangquan, 20000]
    PS C:\Users\zzx21\py文件夹>
    

    因为repr在类程序中的参与,文件运行时,就不是打印实例的单个属性,而是打印实例的若干个属性了。学习了类编程的三个步骤,粗浅地给出这个模仿后得到的笔记。但这个面向对象编程的部分还有若干章待读,本章就有七个步骤,恐怕还得拿时间来消化。

    展开全文
  • 一、类定义:复制代码代码如下:class :类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。如果直接使用类名修改其属性,那么将直接影响到已经实例化的对象类的私有属性:__private_...
  • 简介在Java中我们可以通过反射来根据类名创建类实例,那么在Python我们怎么实现类似功能呢?其实在Python一个builtin函数import,我们可以使用这个函数来在运行时动态加载一些模块。如下:12345def createInstance...
  • Python中动态创建类实例

    万次阅读 2017-03-24 09:15:43
    Python中动态创建类实例简介在Java中我们可以通过反射来根据类名创建类实例,那么在Python我们怎么实现类似功能呢?其实在Python一个builtin函数import,我们可以使用这个函数来在运行时动态加载一些模块。如下:def...
  • 在Java中我们可以通过反射来根据类名创建类实例,那么在Python我们怎么实现类似功能呢?其实在Python一个builtin函数import,我们可以使用这个函数来在运行时动态加载一些模块
  • Python新建一个类,属性和方法

    千次阅读 2019-07-05 23:46:09
    #创建一个类,类名是student class student(): #指定student的属性只能为,name,age __slots__ = ('name','age') #给类创建一个方法,self是类,age是传入参数 def set_age(self,age): #赋值给age self.age ...
  • class Person(object): def __init__(self, name): ...如上,我想在创建person的时候给它声明一个gun属性,但并不想给它赋值,这要怎么搞? 怎么才能在.gun的时候能点出来并且.gun.name也能点出来
  • <p>type创建一个类的方法是 type(name,bases,dict) 比如:a=type('fn',(object,),dict(n=1)) 这个a可以理解是类名fn的实例么? 如果是的话,怎么调用fn创建一个新的实例࿱...
  • Python当中的高级用法,如果你之前从来没见过这术语或者是没听说过这概念,这是非常正常的,因为方面它的使用频率不高,另外方面就是它相对不太容易理解。以至于很多Python开发者都理解得不是很深入,...
  • 首先先创建一个类,比如宇宙只有一个地球class Earth:passa = Earth()print(id(a))b = Earth()print(id(b))运行结果如下:通过打印实例的id可以发现,地球类默认创建了两个实例。那么怎么能够让类...
  • python一个俄罗斯方块小游戏

    千次阅读 多人点赞 2020-12-29 10:21:29
    先用python创建一个py文件 定义这次程序所需要的 import sys import time import pygame from pygame.localsimport * import blocks 然后写出它所需要的模块 SIZE =30 # 每个小方格大小 BLOCK_HEIGHT =2
  • python基本语法--引入Python文件1、新建python文件 :在同目录lib下创建mylib.py和loadlib.py两个文件2、在mylib.py文件中创建一个Hello的类并且给这个类添加一个sayHello的方法,让她输出hello python3、在loadlib....
  • Python-封装对象

    千次阅读 2018-11-10 19:31:42
    正因为如此,在Python创建一个类和对象是很容易的,当然如果习惯面向过程或者函数的写法也是可以的,Python并不做硬性的限制。 接下来一步一步的和大家分享一下Python怎么样封装类的。 版本一: 封装一个类,最...
  • Python

    2019-10-12 09:00:20
    究竟什么是元: ...我要大群的都具有种特点,我怎么给他们加上呢?模板嘛,我从这模板创建一群不就OK了?那就需要元了。 __metaclass__属性: __metaclass__属性是用来指明创建类...
  • python中的元

    2018-03-18 16:51:38
    元类的应用场景下面我们开始来学习:一,python 中元类的概念:在python中我们定义一个类的格式是:class 类名(object):pass只要使用class,python解释器就会创建一个对象!当然在python中还可以通过type来动态...
  • python的元继承的区别

    千次阅读 2018-09-04 17:40:48
    :type函数创建类python中,也是对象。既然是是对象,必然有存在生成它。那么什么东西创建? 答案是type。 怎么去理解? eg:str,这可以创建字符串,类比下type可以创建类。 type函数可以...
  • 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。 面向对象 是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个...
  • python-(class)是什么?怎么用?

    千次阅读 多人点赞 2020-05-07 06:34:29
    之前讲过了面向对象,那么在python中,面向对象就是用类(class)来...那么这个类,就是这样一个模板,我们可以自己去定义一个模板,在我们需要的时候来按照模板创建一个对象,进行调用。 类这个东西事实上我们很早...
  • Python中如何使用

    2020-07-07 14:16:52
    Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。 如果你以前没有接触过面向对象的编程语言,那你可能需要先了解一些...
  • python怎么表示空值

    2021-01-19 23:55:30
    首先了解python对象的概念 python中,万物皆对象,所有的...使用一个类可以创建多个对象实例,即人,猫,狗都属于哺乳动物类。类是对象的抽象化,对象是类的实例化。类不代表具体的事物,而对象表示具体的事物 类也是有
  • python类定义

    2014-04-07 09:13:00
    类实例化后,可以使用其属性,实际上,创建一个类之后,可以通过类名访问其属性。如果直接使用类名修改其属性,那么将直接影响到已经实例化的对象类的私有属性: __private_attrs 两个下划线开头,声...
  • 创建一个脚本文件后,定义了某些函数和变量。你在其他需要这些功能的文件中,导入这模块,就可重用这些函数和变量。一般用module_name.fun_name,和module_name.var_name进行使用。这样的语义用法使模块看起来很...
  • python之《对象和

    2020-08-07 15:09:14
    一,面向对象与面向过程 *面向对象编程:oop是一种...*一个模板,模板里可以包含多个函数,函数里是实现一些功能。 *对象是根据模板创建的实例,通过实例对象可以执行中的函数。 *是对象的抽象化,而对
  • 深入理解python

    千次阅读 2017-01-09 20:57:18
    ——在你定义一个类的时候,就会在内存中创建一个名字为类名的对象。 能够创建对象(实体)的对象(类),就称之为类。(说起来很别扭,但大致就是这么个意思)。 既然是一个对象,那就可以:将它分配给一个变量 ...
  • Python使用说明

    2021-01-21 17:51:45
    霍霍》 定义一个元类(就所一个类的模板!莫多想,还要记住这是类级别的,不是对象级别的!): 复制代码 代码如下: class MyMeta(type): def __init__(cls,name,bases,dic): print cls.__name__ print name def __...
  • PYTHON3中 的继承

    2018-04-12 16:54:00
    继承是一种创建的方式,在python中,新建的可以继承一个或多个父类,也就是说在python中支持一个儿子继承多个爹。 新建的成为子类或者派生。 父类又可以成为基类或者超类。 子类会遗传父类的属性。 2...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 279
精华内容 111
关键字:

python怎么创建一个类

python 订阅