有括号的方法和没有括号的方法有什么区别?

时间:2020-05-11 20:17:55

标签: python typeerror openpyxl

我正在学习OpenPyXL,这是《自动化无聊的东西》教科书的一部分。我的问题与以下代码行有关:

for row in range (2, sheet.max_row + 1): # Starts at the row 2 and steps by 1 until highest row

为什么我在运行Type Error: 'int' object is not callable方法时得到sheet.max_row(),而在删除括号时却没有得到?具有括号的方法之间的区别是什么-例如,sheet.max_row()sheet.max_row之间的区别。我注意到sheet.get_highest_row()方法已由sheet.max_row()取代。

我已经为以下问题生成了代码:

#!/usr/bin/env python3

"""
readCensusExcel.py

Chapter 12 - Project: Reading Date From a Spreadsheet
This program retrieves data counts the total population and the number of census tracts for each county.

"""

import os, openpyxl, pprint

os.chdir('D:\\Python\\Projects - Automate the Boring Stuff with Python\\Chapter 12\\readCensusExcel')
print('Opening workbook...')

wb = openpyxl.load_workbook('censuspopdata.xlsx')
sheet = wb['Population by Census Tract']
countyData = {} # creates a dictionary called countyData

#Fill in countyData with each county's population and tracts
print('Reading rows...')
for row in range (2, sheet.max_row + 1): # Starts at the row 2 and steps by 1 until highest row
    # Each row in the spreadsheet has data for one census tract
    state = sheet['B' + str(row)].value
    county = sheet['C' + str(row)].value
    pop = sheet['D' + str(row)].value 

    # countyData dictionary keys format: countyData[state abbrev][county]['pops'] or countyData[state abbrev][county]['tracts']

    # Make sure the key for this state exists, it will do nothing if the key already exists
    countyData.setdefault(state, {})
    # Make sure the key for this county in this state exists
    countyData[state].setdefault(county, {'tracts': 0, 'pop': 0})

    # Each row represents one census tract, so increment by one
    countyData[state][county]['tracts'] += 1
    # Increase the county pop by the pop in this census tract
    countyData[state][county]['pop'] += int(pop)


# Open a new text fill and write the contents of countyData to it

print('Writing results...')
resultFile = open('census2010.py', 'w')
resultFile.write('allData = ' + pprint.pformat(countyData))
resultFile.close()
print('Done.')

1 个答案:

答案 0 :(得分:0)

要添加更多详细信息,您所指的是属性,而不是方法/函数。如果我们回顾一下类,我们可以看到区别。假设我有一门叫狗的课程:

class Dog():
  def __init__(self, color, name):
    self.color = color
    self.name = name

  def sayName(self):
    print(f"My name is {self.name}")

我们有什么?我的课有两种方法, init ()和sayName()。这些做某事。我可以使用init创建一个新实例,如下所示:

rusty = Dog("black", "Rusty")

我可以通过以下方式来生锈地说他的名字:

rusty.sayName()

rusty是一条狗,sayName()是一种方法。狗可以做的事。但是生锈也有self.name和self.color,这些不是方法,而是属性。当我们运行 init ()时,我们确定了这些属性是什么,但是我们可能拥有的属性并非直接来自传递给init的。我可以添加:

class Dog():
  def __init__(self, color, name):
    self.color = color
    self.name = name
    self.lastname = f"Mc{name[:-1]}erson"

  def sayName(self):
    print(f"My name is {self.name} {self.lastname}")

现在我有3个属性,其中一个我没有直接传递给init方法。如果我现在生锈了:

rusty = Dog("Black", "Rusty")

然后我可以调用sayName(),它将显示:

My name is Rusty McRusterson

但是,我也可以这样做:

print(rusty.lastname)

这将访问该属性并进行打印:

McRusterson

但是,大多数方法不会打印到控制台,它们会返回一个值。像这样:

def sayName(self):
    return f"My name is {self.name} {self.lastname}"

这是令人困惑的地方,因为很难知道您正在访问的值是由函数/方法还是由属性提供的。也许不是在初始化中编写self.lastname定义,而是添加了另一种方法:

class Dog():
def __init__(self, color, name):
    self.color = color
    self.name = name

def lastName(self):
    name_slice = self.name[:-1]
    lastname = f"Mc{name_slice}erson"
    return lastname

def sayName(self):
    print(f"My name is {self.name} {self.lastName()}")

注意我如何将打印语句中的self.lastname更改为self.lastName()?这是因为我想要的值不再是属性,而是方法的结果。唯一了解这种情况的方法是首先了解它是如何编写的,或者在我很棒的狗库中搜寻文档。更糟的是,我还可以将lastName()编写为创建属性.lastname的方法,我将在代码中输入以下内容:

rusty = Dog("Black", "Rusty")
rusty.lastName()
print(rusty.lastname)

不过,另一个提示是,如果某些东西需要传递参数,它将成为方法或函数。也有大小写约定,但这并不是指导性内容。希望这可以解释差异!