李哥深度学习班 Python基础
以前学过一点点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__方法,在创建实例的时候,就把name,score等属性绑上去:
class Student(object):
def __init__(self, name, score):
self.name = name
self.score = score
(我还以为只能用__init__绑定属性)
二、继承和多态
*****************************继承和多态 - Python教程 - 廖雪峰的官方网站*****************************
这篇原文通篇都要看看!!!!!!!!!!
因为是第一次见,全都是新知识,想摘但感觉全都很重要,所以必须好好看看
继承比较好理解:
原文:继承有什么好处?最大的好处是子类获得了父类的全部功能。由于Animal实现了run()方法,因此,Dog和Cat作为它的子类,什么事也没干,就自动拥有了run()方法:
更重要的是多态:(从摘抄位置开始后续的都要看)
>>> isinstance(c, Dog)
True
看来a、b、c确实对应着list、Animal、Dog这3种类型。
但是等等,试试:
>>> isinstance(c, Animal)
True
看来c不仅仅是Dog,c还是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) # 添加新属性
为什么这里必须调用?
-
子类有自己的
__init__:要添加新层(新属性) -
父类有重要的初始化逻辑:
nn.Module.__init__()做了很多重要工作 -
需要保持父类的初始化:同时添加自己的初始化

实际的继承链例子
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)就报错。
更多推荐
所有评论(0)