欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

python简明教程_07

程序员文章站 2022-05-28 20:27:16
...

python编程语言简明教程,翻译自以下仓库:
Python-Lectures
原仓库是一系列的jupyter notebook,可以直接在jupyter环境下运行程序示例。我添加了中文注释,并改为了兼容python3

变量、列表、字典等都是python中的对象;对象是类的实例,类是对象的模板。

例如:“大学”是一个类,“清华大学”是“大学”这个类的一个实例。

如下所示,定义一个新的类:

class class_name:

    Functions
class FirstClass:
    pass

pass 意思是说不做任何操作。

以上就是一个名为FirstClass的类,下面给这个类创建一个名为egclass的实例:

egclass = FirstClass()
type(egclass) 

### type函数返回括号内对象的类型,可以看到,返回了FirstClass
__main__.FirstClass

现在我们来给这个FirstClass增添一些功能。类可以增添一些函数来丰富功能,这些函数被叫做这个类的“方法”。
大多数类都会定义一个叫 “__init__” 的函数。在这个起给实例初始化的作用的函数里,可以给类内部的变量初始化,给一些算法初始化,这些初始化的变量、算法可以被类内的其他方法使用。一个类内部的变量通常被成为一个类的“属性”。

例如,可以让FirstClass包含两个变量name和symbol:

关于以下的“self”稍后会解释。

class FirstClass:
    def __init__(self,name,symbol):
        self.name = name
        self.symbol = symbol

现在我们增添了 __init__ 方法,本质上是一个接受变量的函数。我们可以通过传递函数的方式来创建一个类的实例:

eg1 = FirstClass('one',1)
eg2 = FirstClass('two',2)
print(eg1.name, eg1.symbol)
print(eg2.name, eg2.symbol)

one 1
two 2

dir( ) 函数用来查看一个类的所有方法:

dir(FirstClass)

### 以下除了已定义的init外,还有很多声明了一个类以后,自动内置的方法,这些方法来自在python中定义类时默认继承的基类(注:以下结果的返回基于python 3.5版本):
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__']

dir( ) 也可以返回一个实例的方法和属性

dir(eg1)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'name',
 'symbol']

注意类中属性的名称,在创建实例后访问时要对应得上:

class FirstClass:
    def __init__(self,name,symbol):
        self.n = name
        self.s = symbol

把内部的属性名字现在改为了n和s,

eg1 = FirstClass('one',1)
eg2 = FirstClass('two',2)
print(eg1.name, eg1.symbol)
print(eg2.name, eg2.symbol)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-11-4ab7dec1c737> in <module>
----> 1 print(eg1.name, eg1.symbol)
      2 print(eg2.name, eg2.symbol)

AttributeError: 'FirstClass' object has no attribute 'name'

返回了一个AttributeError, 因为实例中的属性名字叫n和s了,所以找不到name和symbol

dir(eg1)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'n',
 's']
print(eg1.n, eg1.s)
print(eg2.n, eg2.s)

one 1
two 2

现在之前的error就不再出现了。我们可以比较以上的例子:

当声明 self.name 和 self.symbol 时,用 eg1.name 和 eg1.symbol 获取属性的值就不会报错,当声明了 self.n 和 self.s时,用 eg1.n 和 eg1.s 就不会报错。

从以上例子可以看出,声明一个类时的“self”就是指的该类的实例自身。

注意,self不是事先定义好的,是需要写类的人自己定义的。也可以不用“self”这个词,但是使用self这个单词是一种约定俗成的习惯。

class FirstClass:
    def __init__(asdf1234,name,symbol):
        asdf1234.n = name
        asdf1234.s = symbol
### 这里用asdf1234代替self的位置,功能一样
eg1 = FirstClass('one',1)
eg2 = FirstClass('two',2)
print(eg1.n, eg1.s)
print(eg2.n, eg2.s)

one 1
two 2

虽然eg1和eg2是FirstClass类的两个实例,但是eg1和eg2不一定要局限于FirstClass类具有的那些内容。他们可以直接声明一些FirstClass类里没有的其他属性,比如:

eg1.cube = 1
eg2.cube = 8
dir(eg1)
### 实例eg1直接增加了一个cube属性:
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'cube',
 'n',
 's']

和全局变量与局部变量类似,类的属性也有不同的种类。

类属性 : 在一个类中任何的方法之外定义的变量,任何一个该类的实例都可以访问这个变量的值。

实例属性 : 在一个类的方法中定义的变量,只能在该方法中使用,在不同的实例中值都是独有的。

class FirstClass:
    test = 'test'
    def __init__(self,name,symbol):
        self.name = name
        self.symbol = symbol

test就是一个类属性,name是实例属性。

eg3 = FirstClass('Three',3)
print(eg3.test, eg3.name)

### 在创建eg3时,没有对test属性做任何赋值等操作,但是也可以访问,但是name属性需要赋值才行

test Three

给FirstClass添加更多方法:

class FirstClass:
    def __init__(self,name,symbol):
        self.name = name
        self.symbol = symbol
    def square(self):
        return self.symbol * self.symbol
    def cube(self):
        return self.symbol * self.symbol * self.symbol
    def multiply(self, x):
        return self.symbol * x
eg4 = FirstClass('Five',5)
print(eg4.square())
print(eg4.cube())

25
125

eg4.multiply(2)

10

以上的操作也可以写作:

FirstClass.multiply(eg4,2)

10

继承

有时候,一个新的类想要使用一个已经写好的类的特性,这个新的类可以通过“继承”这个已有类来实现这一目的。

例如以下的SoftwareEngineer类具有一个叫salary的方法:

class SoftwareEngineer:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def salary(self, value):
        self.money = value
        print(self.name,"earns",self.money)

a = SoftwareEngineer('Kartik',26)
a.salary(40000)

Kartik earns 40000

dir(SoftwareEngineer)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'salary']

现在再写一个Artist类,包含money和artform两个方法:

class Artist:
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def money(self,value):
        self.money = value
        print(self.name,"earns",self.money)
    def artform(self, job):
        self.job = job
        print(self.name,"is a", self.job)

b = Artist('Nitin',20)
b.money(50000)
b.artform('Musician')

Nitin earns 50000
Nitin is a Musician

dir(Artist)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'artform',
 'money']

可以看出,salary这个函数和money这个函数其实执行的操作是完全一样的。因此我们可以通过让Artist类继承SoftwareEngineer类来让Artist也具有salary方法,这样就不用在Artist类中再写一遍了。

class Artist(SoftwareEngineer):
    def artform(self, job):
        self.job = job
        print(self.name,"is a", self.job)
        
### 使用Artist(SoftwareEngineer)这种写法,就是让Artist继承了SoftwareEngineer类,不但继承了salary这个函数,也继承了init方法中的属性
c = Artist('Nishanth',21)
dir(Artist)
['__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 'artform',
 'salary']
c.salary(60000)
c.artform('Dancer')

Nishanth earns 60000
Nishanth is a Dancer

假如某个继承来的方法不适合新的类,也可以通过重写同名函数的方法来将该类方法覆盖。

class Artist(SoftwareEngineer):
    def artform(self, job):
        self.job = job
        print(self.name,"is a", self.job)
    def salary(self, value):
        self.money = value
        print(self.name,"earns",self.money)
        print("I am overriding the SoftwareEngineer class's salary method")
### 在这里salary这个方法被重写了

c = Artist('Nishanth',21)
c.salary(60000)
c.artform('Dancer')

Nishanth earns 60000
I am overriding the SoftwareEngineer class’s salary method
Nishanth is a Dancer

如果不确定将调用多少次方法,则很难声明这么多变量来储存每次调用产生的不同的值。所以最好是声明一个列表,每次向列表中增加元素。

class emptylist:
    def __init__(self):
        self.data = [] ### 声明了一个空列表,后续不论多少次调用以下的one two three方法,都可以把结果放在这个列表里。
    def one(self,x):
        self.data.append(x)
    def two(self, x ):
        self.data.append(x**2)
    def three(self, x):
        self.data.append(x**3)

xc = emptylist()
xc.one(1)
print(xc.data)

[1]

因为写emptylist的时候,已经声明了data是一个列表,所以列表的各种操作也适用于data,例如可以直接追加数据:

xc.data.append(8)
print(xc.data)

[1, 8]

xc.two(3)
print(xc.data)

[1, 8, 9]

如果想让一个类可以处理不同数量的属性,可以像之前那样用星号变量的方式来处理:

class NotSure:
    def __init__(self, *args):
        self.data = ''.join(list(args)) 
yz = NotSure('I', 'Do' , 'Not', 'Know', 'What', 'To','Type')
yz.data

‘IDoNotKnowWhatToType’

(注:以下是作者写在最后的话,属于纯机翻,只是为了好玩)

从这往哪儿走

单独练习可以帮助您掌握python的窍门:给出自己的问题并加以解决。您也可以注册任何竞争性编码平台以获取竞赛编程题。您编写的代码越多,发现的内容就越多,您对这门语言的欣赏也就越多。

现在,您已经了解了python,可以在您感兴趣的领域尝试使用不同的python库。我强烈建议您查看这份精选的Python框架,库和软件列表http://awesome-python.com

python官方文档 : https://docs.python.org/2/

因为寿命短,所以解决问题,您需要python!

和平.

Rajath Kumar M.P ( rajathkumar dot exe at gmail dot com)