以前学过一点点python的基础语法(很基础),后面一直用的c。

把基础捡一捡,再在这里记录一些不太熟悉的用法

一、类

*************************************************************

这里从原文的评论里摘一段:

上帝

class 类 (人) instance 实例 (你,我,他) 你会有些属性(身高,年龄,体重) 你会有些技能(吃饭,泡妞)

__init__ 方法的主要作用,就是初始化你的属性,这些属性,在上帝初始化你的时候就要赋予给你,比如zhangsan = Person(170,29,50)这时上帝就把你创造出来了,也就是实例化了你,然后,你到底有哪些技能呢,这就看有没有在类里面定义了,如果有定义泡妞的技能,那么你就可以调用泡妞的技能来泡妞,大致就是这样吧,看看下面的例子就更清楚了

class Person(object):
# 这里就是初始化你将要创建的实例的属性
    def __init__(self,hight,weight,age):
        self.hight = hight
        self.weight = weight
        self.age = age

# 定义你将要创建的实例所有用的技能
    def paoniu(self):
        print('你拥有泡妞的技能')

    def eat(self):
        print('you can eat')

# 开始创建实例
zhangsan=Person(170,50,29)
lisi = Person(175,100,30)

# 你的实例开始使用它的技能
zhangsan.paoniu()
lisi.eat()

此外还有:

可以自由地给一个实例变量绑定属性,比如,给实例bart绑定一个name属性

(这里的Student类是空的,详细看原文)

>>> bart.name = 'Bart Simpson'
>>> bart.name
'Bart Simpson'

由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把namescore等属性绑上去:

class Student(object):
    def __init__(self, name, score):
        self.name = name
        self.score = score

(我还以为只能用__init__绑定属性)

二、继承和多态

*****************************继承和多态 - Python教程 - 廖雪峰的官方网站*****************************

                                        这篇原文通篇都要看看!!!!!!!!!!

因为是第一次见,全都是新知识,想摘但感觉全都很重要,所以必须好好看看

继承比较好理解:

原文:继承有什么好处?最大的好处是子类获得了父类的全部功能。由于Animal实现了run()方法,因此,DogCat作为它的子类,什么事也没干,就自动拥有了run()方法:

更重要的是多态:(从摘抄位置开始后续的都要看)

>>> isinstance(c, Dog)
True

看来abc确实对应着listAnimalDog这3种类型。

但是等等,试试:

>>> isinstance(c, Animal)
True

看来c不仅仅是Dogc还是Animal

不过仔细想想,这是有道理的,因为Dog是从Animal继承下来的,当我们创建了一个Dog的实例c时,我们认为c的数据类型是Dog没错,但c同时也是Animal也没错,Dog本来就是Animal的一种!

所以,在继承关系中,如果一个实例的数据类型是某个子类,那它的数据类型也可以被看做是父类。但是,反过来就不行:

>>> b = Animal()
>>> isinstance(b, Dog)
False

Dog可以看成Animal,但Animal不可以看成Dog

实例属性和类属性 - Python教程 - 廖雪峰的官方网站

用self定义的,或者直接用实例.xxx=定义的属性属于这个实例自己的属性,但是如果

class Student(object):
    name = 'Student'

像这样定义的就是类属性,是这一整个类所共有的属性,当我们定义了一个类属性后,这个属性虽然归类所有,但类的所有实例都可以访问到。

>>> class Student(object):
...     name = 'Student'
...
>>> s = Student() # 创建实例s
>>> print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
Student
>>> print(Student.name) # 打印类的name属性
Student
>>> s.name = 'Michael' # 给实例绑定name属性
>>> print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
Michael
>>> print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
Student
>>> del s.name # 如果删除实例的name属性
>>> print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
Student

类继承中 super()的作用

super().__init__()是为了调用父类的构造函数,确保子类正确继承父类的所有属性和方法。

情况1:不需要调用 super() 的例子(你的动物类)

class Animal:
    def run(self):
        print('Animal is running...')

class Dog(Animal):
    pass  # 没有定义 __init__

dog = Dog()
dog.run()  # 正常执行

为什么这里不需要 super()?

1、子类没有 __init__ 方法:
Python会自动寻找并使用父类的 __init__(实际上调用了 object.__init__()(最顶层的父类))

2、父类 Animal 也没有定义 __init__: 
同样继承自 object 的默认 __init__,默认的 object.__init__() 什么也不做

3、只是继承方法,不添加新属性:
如果子类不需要初始化自己的属性,直接继承父类的方法就足够了

情况2:必须调用 super() 的例子(神经网络)

class MyAlexNet(nn.Module):
    def __init__(self):
        super().__init__()  # 必须调用
        self.conv1 = nn.Conv2d(3, 64, 11)  # 添加新属性

为什么这里必须调用?

  1. 子类有自己的 __init__:要添加新层(新属性)

  2. 父类有重要的初始化逻辑nn.Module.__init__() 做了很多重要工作

  3. 需要保持父类的初始化:同时添加自己的初始化

实际的继承链例子

class A:
    def __init__(self):
        print("A init")
        self.a_value = 10

class B(A):
    def __init__(self):
        print("B init")
        self.b_value = 20
        # 忘记调用 super().__init__()

b = B()
print(b.a_value)  # ❌ 报错:AttributeError,因为A的初始化没执行

修复:

class B(A):
    def __init__(self):
        super().__init__()  # ✅ 先调用父类初始化
        print("B init")
        self.b_value = 20

b = B()
print(b.a_value)  # ✅ 输出:10
print(b.b_value)  # ✅ 输出:20

三、yield与生成器对象:

****************************************************************

这里简单摘一些:

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator函数,调用一个generator函数将返回一个generator

这里,最难理解的就是generator函数和普通函数的执行流程不一样。普通函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

举个简单的例子,定义一个generator函数,依次返回数字1,3,5:

def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)

调用该generator函数时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值:

>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2
3
>>> next(o)
step 3
5
>>> next(o)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

可以看到,odd不是普通函数,而是generator函数,在执行过程中,遇到yield就中断,下次又继续执行。执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(o)就报错。

更多推荐