python简明教程_07

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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值