{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 类" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python中的变量、列表、字典等其实都是类,因为Python从设计之初就已经是一门面向对象的语言。\n", "\n", "本节常见的定义和概念定义:\n", "* 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例\n", "* 对象(Object):通过类定义的数据结构实例(Instance),对象包括两类成员(类变量和实例变量)和方法。例如我们定义了一个 `Person` 类,而具体的人,比如小明,小黄就是 `Person` 类的实例\n", "* 属性: 描述该类具有的特征,比如人类具备的属性,身份证,姓名,性别,身高,体重等等都是属性\n", "* 方法: 该类对象的行为,例如这个男孩会打篮球,那个女孩会唱歌等等都是属于方法,常常通过方法改变一些类中的属性值" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "类声明如下:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "```\n", "class class_name:\n", "\n", " Functions\n", "```" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "# 一个最简单的类\n", "class FirstClass:\n", " pass\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "NOTE: **pass** 在Python中意味着什么都不做。 " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "上面声明了一个名为“FirstClass”的类对象,现在考虑一个具有“FirstClass”所有特征的“egclass”。所以你所要做的就是,将“egclass”等同于“FirstClass”。在python术语中,这称为创建实例。“egclass”是“FirstClass”的实例" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "egclass = FirstClass()" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "__main__.FirstClass" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(egclass)" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "type" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "type(FirstClass)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "现在让我们向类中添加一些“功能”。这样我们的FirstClass就有了更好的定义。类内的函数被称为该类的“方法”" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "大多数类都有一个名为`__init__`的函数,这些被称为魔术方法。在这个方法中,你基本上初始化了这个类的变量,或者任何适用于这个方法中指定的所有方法的初始化算法。类中的变量称为属性。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "当构造函数被定义后,`__init__`被调用,这样初始化实例被创建。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "我们构造我们的`FirstClass`去接受两个变量名称和符号。\n", "\n", "我将会在稍后解释`self`。" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class FirstClass:\n", " \"\"\"My first class\"\"\"\n", " class_var = 10\n", " def __init__(self,name,value):\n", " self.name = name\n", " self.value = value" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "现在我们已经定义了一个函数而且添加了`__init__`方法。我们可以创建一个名为FirstClass的实例,该实例现在接受两个参数。" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "eg1 = FirstClass('one',1)\n", "eg2 = FirstClass('two',2)" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one 1\n", "two 2\n", "My first class\n" ] } ], "source": [ "print(eg1.name, eg1.value)\n", "print(eg2.name, eg2.value)\n", "print(eg1.__doc__)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**dir( )** 函数在查看类包含什么以及它提供了什么方法时非常方便。" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "scrolled": false }, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " 'class_var']" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(FirstClass)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'My first class'" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "FirstClass.__doc__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "实例的**dir()** 也显示了它定义的属性。" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " 'class_var',\n", " 'name',\n", " 'value']" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(eg1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "稍微改变一下FirstClass函数," ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class FirstClass:\n", " def __init__(self,name,value):\n", " self.n = name\n", " self.v = value" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "将self.name和self.symbol转化成self.n和self.s会得到:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": true }, "outputs": [], "source": [ "eg1 = FirstClass('one',1)\n", "eg2 = FirstClass('two',2)" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "ename": "AttributeError", "evalue": "'FirstClass' object has no attribute 'name'", "output_type": "error", "traceback": [ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0meg1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0meg1\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msymbol\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0meg2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0meg2\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msymbol\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", "\u001b[0;31mAttributeError\u001b[0m: 'FirstClass' object has no attribute 'name'" ] } ], "source": [ "print(eg1.name, eg1.symbol)\n", "print(eg2.name, eg2.symbol)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "AttributeError, 还记得变量就是类中的属性吗?因此,这意味着我们没有为实例提供正确的属性。" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " 'n',\n", " 'v']" ] }, "execution_count": 17, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(eg1)" ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one 1\n", "two 2\n" ] } ], "source": [ "print(eg1.n, eg1.v)\n", "print(eg2.n, eg2.v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "现在我们解决了这个错误。现在让我们比较一下我们看到的两个例子。\n", "\n", "当我声明self.name和self.value,使用eg1.name和eg1.value没有属性错误。当我声明self.n和self.s时,使用eg1.n和eg1.s没有属性错误。\n", "\n", "从以上我们可以得出**self**就是实例本身。\n", "\n", "记住,**self**不是Python的关键词,它是用户定义的。你可以利用任何你觉得舒服的东西。但是使用self已经成为一种常见的做法。" ] }, { "cell_type": "code", "execution_count": 19, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class FirstClass:\n", " def __init__(asdf1234,name,value):\n", " asdf1234.n = name\n", " asdf1234.v = value" ] }, { "cell_type": "code", "execution_count": 20, "metadata": { "collapsed": true }, "outputs": [], "source": [ "eg1 = FirstClass('one',1)\n", "eg2 = FirstClass('two',2)" ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "one 1\n", "two 2\n" ] } ], "source": [ "print(eg1.n, eg1.v)\n", "print(eg2.n, eg2.v)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "因为eg1和eg2是FirstClass的实例,所以它不需要被限制在FirstClass本身。它可以通过声明其他属性来扩展自己,而不需要在FirstClass中声明属性。" ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "collapsed": true }, "outputs": [], "source": [ "eg1.cube = 1\n", "eg2.cube = 8" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " 'cube',\n", " 'n',\n", " 'v']" ] }, "execution_count": 23, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(eg1)" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "就像我们前面看到的全局变量和局部变量一样,即使类也有自己的变量类型。\n", "\n", "**类属性**:在方法外部定义的属性,适用于所有实例。\n", "\n", "**实例属性**:在方法内部定义的属性,只适用于该方法,并且对每个实例都是唯一的。" ] }, { "cell_type": "code", "execution_count": 24, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class FirstClass:\n", " test = 'test'\n", " def __init__(self,name,value):\n", " self.name = name\n", " self.value = value" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "这里test是一个类属性,而name是一个实例属性。" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test4\n" ] } ], "source": [ "eg3 = FirstClass('Three',3)\n", "eg4 = FirstClass('Four', 4)\n", "eg4.test = 'test4'\n", "print(eg4.test)" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "test Three\n" ] } ], "source": [ "print(eg3.test, eg3.name)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "让我们添加更多的方法到FirstClass。" ] }, { "cell_type": "code", "execution_count": 28, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class FirstClass:\n", " def __init__(self,name,value):\n", " self.name = name\n", " self.value = value\n", " def square(self):\n", " return self.value * self.value\n", " def cube(self):\n", " return self.value * self.value * self.value\n", " def multiply(self, x):\n", " return self.value * x" ] }, { "cell_type": "code", "execution_count": 29, "metadata": { "collapsed": true }, "outputs": [], "source": [ "eg4 = FirstClass('Five',5)" ] }, { "cell_type": "code", "execution_count": 30, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "25\n", "125\n" ] } ], "source": [ "print(eg4.square())\n", "print(eg4.cube())" ] }, { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 27, "metadata": {}, "output_type": "execute_result" } ], "source": [ "eg4.multiply(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "以上也可以写成:" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 28, "metadata": {}, "output_type": "execute_result" } ], "source": [ "FirstClass.multiply(eg4,2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## 2. 继承" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "在某些情况下,新类需要具有已定义类的所有特征。因此,新类可以“继承”前一个类,并向其添加自己的方法,这称为继承。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "考虑类Person类具有薪水的方法。" ] }, { "cell_type": "code", "execution_count": 31, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Person:\n", " def __init__(self,name,age):\n", " self.name = name\n", " self.age = age\n", " def salary(self, value):\n", " self.money = value\n", " print(self.name,\"earns\",self.money)" ] }, { "cell_type": "code", "execution_count": 32, "metadata": { "collapsed": true }, "outputs": [], "source": [ "a = Person('Jerry',26)" ] }, { "cell_type": "code", "execution_count": 33, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Jerry earns 40000\n" ] } ], "source": [ "a.salary(40000)" ] }, { "cell_type": "code", "execution_count": 34, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " 'salary']" ] }, "execution_count": 34, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(Person)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "现在考虑另一个Artist类,告诉我们艺术家挣的钱的数量和他的艺术形式。" ] }, { "cell_type": "code", "execution_count": 35, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Artist:\n", " def __init__(self,name,age):\n", " self.name = name\n", " self.age = age\n", " def salary(self,value):\n", " self.money = value\n", " print(self.name,\"earns\",self.money)\n", " def artform(self, job):\n", " self.job = job\n", " print(self.name,\"is a\", self.job)" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": true }, "outputs": [], "source": [ "b = Artist('Nick',20)" ] }, { "cell_type": "code", "execution_count": 37, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Nick earns 50000\n", "Nick is a Musician\n" ] } ], "source": [ "b.salary(50000)\n", "b.artform('Musician')" ] }, { "cell_type": "code", "execution_count": 38, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " 'artform',\n", " 'salary']" ] }, "execution_count": 38, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(Artist)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "money 方法和salary 方法是一样的。因此,我们可以将该方法推广到工资类,并将软件工程师类继承到美术师类。现在艺术类变成了," ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Artist(Person):\n", " def artform(self, job):\n", " self.job = job\n", " print(self.name,\"is a\", self.job)" ] }, { "cell_type": "code", "execution_count": 41, "metadata": { "collapsed": true }, "outputs": [], "source": [ "c = Artist('Tom',21)" ] }, { "cell_type": "code", "execution_count": 42, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "['__class__',\n", " '__delattr__',\n", " '__dict__',\n", " '__dir__',\n", " '__doc__',\n", " '__eq__',\n", " '__format__',\n", " '__ge__',\n", " '__getattribute__',\n", " '__gt__',\n", " '__hash__',\n", " '__init__',\n", " '__le__',\n", " '__lt__',\n", " '__module__',\n", " '__ne__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " '__weakref__',\n", " 'artform',\n", " 'salary']" ] }, "execution_count": 42, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(Artist)" ] }, { "cell_type": "code", "execution_count": 43, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tom earns 60000\n", "Tom is a Dancer\n" ] } ], "source": [ "c.salary(60000)\n", "c.artform('Dancer')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "假设在继承一个特定方法的时候,该方法不适合新类。可以通过在新类中用相同的名称再次定义该方法来重写该方法。" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class Artist(Person):\n", " def artform(self, job):\n", " self.job = job\n", " print(self.name,\"is a\", self.job)\n", " def salary(self, value):\n", " self.money = value\n", " print(self.name,\"earns\",self.money)\n", " print(\"I am overriding the SoftwareEngineer class's salary method\")" ] }, { "cell_type": "code", "execution_count": 46, "metadata": { "collapsed": true }, "outputs": [], "source": [ "c = Artist('Tom',21)" ] }, { "cell_type": "code", "execution_count": 47, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Tom earns 60000\n", "I am overriding the SoftwareEngineer class's salary method\n", "Tom is a Dancer\n" ] } ], "source": [ "c.salary(60000)\n", "c.artform('Dancer')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "如果输入参数的数量因实例而异,则可以使用星号。" ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": true }, "outputs": [], "source": [ "class NotSure:\n", " def __init__(self, *args):\n", " self.data = ' '.join(list(args)) " ] }, { "cell_type": "code", "execution_count": 48, "metadata": { "collapsed": true }, "outputs": [], "source": [ "yz = NotSure('I', 'Do' , 'Not', 'Know', 'What', 'To','Type')" ] }, { "cell_type": "code", "execution_count": 49, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'I Do Not Know What To Type'" ] }, "execution_count": 49, "metadata": {}, "output_type": "execute_result" } ], "source": [ "yz.data" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# 3. 接下来应该怎么做" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "为了学好Python,仅仅看教程是不够的,需要做大量的练习题。可以使用教程里所列的练习题,也可以自己找各个方面的练习题。\n", "\n", "* 编程比较重要的培养编程思维,如果抄别人写好的代码,发现不了Python的窍门、技巧,因此需要独立自主完成编程练习,也可以给自己出一些小项目,并解决它们。\n", "* 你编写的代码越多,你发现的越多,你就越开始欣赏这门语言。\n", "* 强烈建议把[《Python作业》](https://gitee.com/pi-lab/machinelearning_homework/blob/master/homework_01_python/README.md)完成\n", "* 在完成基本的编程习题之后,可以在[《其他编程练习》](https://gitee.com/pi-lab/machinelearning_homework/blob/master/homework_01_python/README.md#references)里面找一些练习题或者项目做一下。\n", "\n", "现在已经介绍了Python,可以尝试感兴趣的领域中的不同Python库。强烈建议查看这个Python框架、库和软件列表 http://awesome-python.com\n", "\n", "\n", "Python 教程:\n", "* [Python tutorial (廖雪峰)](https://www.liaoxuefeng.com/wiki/1016959663602400)\n", "* [Python基础教程](https://www.runoob.com/python/python-tutorial.html)\n", "* [Python官方教程(中文版)](https://docs.python.org/zh-cn/3/tutorial/index.html)\n", "* [Python官方文档](https://docs.python.org/3/)\n", "* [跟海龟学Python](https://gitee.com/pi-lab/python_turtle)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## **最后,享受解决问题的快乐!因为生命短暂,你需要Python!**" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.5.4" } }, "nbformat": 4, "nbformat_minor": 1 }