我一直在努力学习课程一段时间。是否有任何人可以帮助我理解使用类。非常感谢任何帮助。
直接调用def scrapper时,下面的代码有效。 Scrapper类是我对类的解释。我相信我现在想要调用实例,但我不确定究竟是怎么回事。该脚本不会产生任何错误,所以我很丢失。谢谢,我希望这是一个合适的问题。
import requests
import re
from bs4 import BeautifulSoup as BS
class Scrapper():
def __init__(self):
self = self
def requests(self):
url_var = raw_input("Please input url: ")
url = requests.get('%s' %url_var, auth=('',''))
return BS(url.text)
def file_(self):
with open("Desktop/Scripts/%s.txt"%url_var,"w+") as links:
return links.write(self)
def parse(self):
links = self .find_all('a')
for tag in links:
link = tag.get('href',None)
if link != None:
return link
else:
print "Error in parsing html"
if __name__ == "__main__":
Scrapper()
###
def scrapper():
url_var = raw_input("Please input url: ")
url = requests.get('%s' %url_var, auth=('user','pass'))
with open('Desktop/Scripts/formgrab.txt',"w+") as links:
soup = BS(url.text)
links.write(soup.prettify().encode('utf8'))
links = soup.find_all('a')
for tag in links:
link = tag.get('href',None)
if link != None:
print link
###
答案 0 :(得分:16)
你在这里问了一个非常广泛的问题,这可能是网站上的主题,但它让我很烦恼,没有人可以向你解释一个如此根本和的主题现代节目的关键,无论如何我都会回答你。这个禅的那一刻,你也试图长时间地躲避我,所以我理解。
警告:未来的长篇教程。不适合胆小的人。
这可能有点刺耳,但由于您正在尝试理解课程,您已经错了。如果您仔细考虑找到类的位置,您可能已经明白了原因。类是面向对象编程的一部分。你看?围绕对象的编程。所以我们不应该谈论课程,我们应该谈论对象。我们稍后会上课。
你说elsewhere:
我已经阅读了几个教程...我理解这些类用于存储数据和布局蓝图,我从来没有理由使用它们因此它永远不会沉没in。我已经阅读了很多教程,里面写着如何创建“类狗”,“猫类”,“#dog; name =" scruff& #34;',但对于我的生活,我无法看到它如何适用于我的情况。无论如何,谢谢你们,抱歉浪费你的时间。
嗯,我很抱歉这些教程浪费了你的时间。在这种情况下,我当然不认为你是唯一一个。
这些教程试图封装的内容是OOP的一部分,它非常有用:对象很好地模拟现实世界的数据。但这仅仅是大局的一部分,所以让我们支持。在我们试图理解为什么对象有用之前,它们是什么?我的意思是,如果您阅读其中一些教程,您就会认为对象可以任何(意思是,它可以模型任何东西),但是既然我们人类倾向于通过打破它们并将它们包围起来来理解事物,那么这个定义就是如此普遍,几乎毫无意义。
{p> a really great blog post fellow Stack Overflow user我认为paradigm非常简洁(强调原文):面向对象的编程是关于对象:状态和行为的捆绑。其余的是可选的绒毛。
状态和行为。这就是制造物体的原因。 (我真的建议你给帖子一个完整的阅读,但我离题了。)
正如您在前面提到的教程中看到的那样,人们对OOP感到非常兴奋的部分原因是能够使用编程对象来模拟真实世界的事物 。这可以追溯到状态和行为。但是,由于我们的程序中没有任何狗和猫,所以很难看到连接。但是一切都说OOP真的很好而且无处不在所以你应该使用它,对吗?这导致人们在不理解对象的情况下采用OOP的部分,并导致错误的重构。这个问题的标题显示了这种想法:我有一个巨大的功能,但每个人都说我应该使用类,所以我应该把它变成一个类,对吧?错误。至少,不一定。
首先,应该注意的是,面向对象的编程虽然很受欢迎,但只有一个functional programming。在imperative中,一切都基于函数而不是对象,有一些非常有趣的效果。 Python部分支持函数式编程,包括map
和reduce
之类的东西,并且存在许多类似于shellcript的Python程序,这些程序很简单grok。我的观点是,一般来说,如果你为了使用OOP而限制自己只使用OOP,那么它会产生不好的结果,如果你用Python(一种多范式语言)来做这件事,你就会不必要地将自己限制在一个子集中。语言的力量。
当帮助您更好地概念化问题和/或帮助您组织程序时,您应该使用对象。对象不仅仅是代码重用!您可以轻松地仅使用函数重用代码。几十年来,这是重用代码的唯一方式。使用对象的真正原因是,当你习惯这样做时,它提供了一个自然的框架来解决程序员每天面临的艰难决策:这个函数应该在哪里生活?做这个或那个应该控制什么?当一切都被分解为对象时,这些问题的答案开始变得更加明显。
假设您正在编写一个程序,它会告诉您文件中最长的单词。忘记图书馆和时尚的单行。让我们这样做:
longest_word = ''
longest_word_len = 0
with open('some_file.txt') as f:
for line in f:
for word in line.split():
word_len = len(word)
if word_len > longest_word_len:
longest_word_len = word_len
longest_word = word
print('The longest word is', longest_word, 'at', longest_word_len, 'characters.')
喂!这非常整洁,而且效果很好。如果我不想在任何时候运行它而不必更改文件名,那肯定会很好......如果我把它放在一个函数中,我可以在它的目录中抛出一个__init__.py
导入它!
def longest_word_in_file(filename):
"""Print a message about the longest word in the given file"""
longest_word = ''
longest_word_len = 0
with open(filename) as f:
for line in f:
for word in line.split():
word_len = len(word)
if word_len > longest_word_len:
longest_word_len = word_len
longest_word = word
print('The longest word is', longest_word, 'at',
longest_word_len, 'characters.')
在那里,只有两个简单的修改,我们有力地将这些代码重构为我们可以导入到其他要使用的地方的东西,以及可以为我们提供所需结果的东西。 em>任何文件,而不仅仅是我们最初硬编码的文件。 (顺便提一下,这使它可以重复使用,不是吗?)我们还给它一个有用的名称,表明它的作用(提示:行为)。
假设我们为这个功能感到骄傲,我们会向所有朋友展示我们所做的事情,并且有一位朋友评论,"酷!什么是有史以来最长的词?"嗯,好问题。现在,我们的小功能只是完成它的工作,然后打包并称它为一天。它没有跟踪呼叫之间的任何。没错:它的州少了!你的朋友询问有关另一次重构的要求的统计数据:这一次是对象。
现在考虑我们的先决条件:州和行为。我们知道它的作用以及它需要跟上的步伐。但是我们还需要考虑第三件事:它是什么?编写函数时,您只考虑它的作用。现在我们需要知道它是什么。由于它找到了文件中最长的单词,因此我说它是LongestWordFinder
。有创意,我知道。
class LongestWordFinder():
"""
Find the longest word in a file and track statistics on words found.
"""
longest_word = ''
longest_word_len = 0
longest_word_ever = ''
longest_word_ever_len = 0
def find_in_file(self, filename):
self.longest_word = ''
self.longest_word_len = 0
with open(filename) as f:
for line in f:
for word in line.split():
word_len = len(word)
if word_len > self.longest_word_len:
self.longest_word_len = word_len
self.longest_word = word
if word_len > self.longest_word_ever_len:
self.longest_word_ever_len = word_len
self.longest_word_ever = word
print('The longest word is', self.longest_word, 'at',
self.longest_word_len, 'characters.')
print('The longest word I have ever seen is',
self.longest_word_ever, 'at', self.longest_word_ever_len,
'characters.')
哇...变了很多。好吧,不是真的。我们的功能现在存在于一个类中,并且具有不同的名称。此外,我们现在正在跟踪两件事:当前文件中最长的单词和扫描的最长单词。唯一真正改变的是在一些地方使用 self 来访问变量,这些变量现在属于类而不仅仅是函数的本地变量。这就是状态在呼叫之间持续存在的方式!
所以这是一个有趣的问题,问自己,如果你还在读这个:永远多长时间?你知道吗,就像我们曾经看到的最长的一句话一样?这也将告诉我们另一个问题的答案:我们究竟如何使用这个东西?如果将该类复制到lwf.py
,则在该目录中打开Python解释器:
>>> from lwf import LongestWordFinder
>>> lwf = LongestWordFinder()
>>> lwf.find_in_file('test.txt')
The longest word is watermelon at 10 characters.
The longest word I have ever seen is watermelon at 10 characters.
>>> lwf.find_in_file('test2.txt')
The longest word is freakshow at 9 characters.
The longest word I have ever seen is watermelon at 10 characters.
为了使用我们的课程,我们必须实例化它。也就是说,我们创建了一个实例。因此,最长的单词 it 有永远看到,意味着实例在其生命周期中看到的最长单词。由于实例与变量绑定,因此它基本上是变量的范围。当我关闭Python解释器时,我复制了该代码,实例消失了 - 它的生命周期结束了 - 并且它跟上的所有状态都消失了。另外,如果我们创建另一个实例:
>>> lwf2 = LongestWordFinder()
>>> lwf2.find_in_file('test.txt')
The longest word is freakshow at 9 characters.
The longest word I have ever seen is freakshow at 9 characters.
它有不同的记忆。它从未见过test.txt
,所以它对西瓜一无所知。
>>> lwf.find_in_file('test2.txt')
The longest word is freakshow at 9 characters.
The longest word I have ever seen is watermelon at 10 characters.
第一个仍然可以。
如果我们想要在关闭Python解释器后记住状态怎么办?好吧,如果我们想要真正的幻想,我们可以使用数据库,但我们只是简单地做事。让我们把它写在一个文件中。在我们处理它的同时,让我们重构我们的类,以便我们可以将它传递给它。
class LongestWordFinder():
"""
Find the longest word in a file and track statistics on words found.
"""
def __init__(self, memory_file=None):
self.longest_word = ''
self.longest_word_len = 0
if memory_file is not None:
with open(memory_file) as memory:
word, word_len = memory.read().strip().split(':')
self.longest_word_ever = word
self.longest_word_ever_len = word_len
else:
self.longest_word_ever = ''
self.longest_word_ever_len = 0
def find_in_file(self, filename):
self.longest_word = ''
self.longest_word_len = 0
with open(filename) as f:
for line in f:
for word in line.split():
word_len = len(word)
if word_len > self.longest_word_len:
self.longest_word_len = word_len
self.longest_word = word
if word_len > self.longest_word_ever_len:
self.longest_word_ever_len = word_len
self.longest_word_ever = word
print('The longest word is', self.longest_word, 'at',
self.longest_word_len, 'characters.')
print('The longest word I have ever seen is',
self.longest_word_ever, 'at', self.longest_word_ever_len,
'characters.')
def save(self, memory_file):
with open(memory_file, 'w') as memory:
memory.write('%s:%s' % (self.longest_word_ever,
self.longest_word_ever_len))
这里发生了两件事。一,我们有一个新方法save
,它在一个文件中写入,以便记住它所见过的最长的单词。第二,我们现在有一个__init__
方法为我们设置状态,包括如果我们给它一个那么读取该文件。你可能已经注意到__something__
意味着它是一个魔法" Python做的事情它允许我们覆盖。在__init__
的情况下,在您创建实例时设置的功能。现在,假设我们已经运行了一两次,称为save,然后退出我们的翻译,当我们重新启动时,我们可以这样做:
>>> lwf = LongestWordFinder('memory.txt')
>>> lwf.longest_word_ever
'watermelon'
我们回到了我们开始的地方。
正如您所看到的,有充分的理由想要将函数重构为类。还有一些不好的。您可能还注意到,有可能解释对象的好处,而从未提及过狗,猫,构造函数,封装甚至继承!*对象很棒,因为它们为您提供了一种跟踪状态的方法,同时提供了直观的方式来为您的程序建模,并轻松地让您传递已经工作的代码,而不会使用一英里长的参数列表的函数。希望这有助于你{{3}}为什么对象有用,以及何时以及为什么你可能想要转变一个巨大的功能"合而为一。快乐的编码。 :)
*尽管这些都是很棒的事情
答案 1 :(得分:4)
当你上课时,你通常会这样做,因为你想要在某种程度上重复使用代码。这可以通过至少两种方式完成。首先,您可以拥有同一类的不同实例,这些实例根据实例的创建方式在实例中存储数据。重用类的另一种方法是使用继承。使用继承,您可以定义一个基类,该基类定义类的一般行为,并让子类优化该行为以执行特定的操作。例如:
import requests
import re
from bs4 import BeautifulSoup as BS
class Scrapper(object):
def __init__(self, url, output_dir):
# store url string on instance
self.url = url
self.output_dir = output_dir
def make_request(self):
# make a request to get the url and save the response on the instance
self.response = requests.get(self.url, auth=('',''))
self.soup = BS(self.response.text)
def output(self):
with open("%s" % self.output_dir, "w") as output_file:
for element in self.get_elements():
output_file.write(element + '\n')
def get_elements(self):
raise NotImplementedError
class HrefScrapper(Scrapper):
def get_elements(self):
elements = []
links = self.soup.find_all('a')
for tag in links:
link = tag.get('href',None)
if link != None:
elements.append(link)
else:
print "Error in parsing html"
return elements
class ImageScrapper(Scrapper):
def get_elements(self):
elements = []
links = self.soup.find_all('img')
for tag in links:
link = tag.get('src',None)
if link != None:
elements.append(link)
else:
print "Error in parsing html"
return elements
if __name__ == "__main__":
amazon_href_scrapper = HrefScrapper('http://www.amazon.com', 'amazon_href.txt')
amazon_href_scrapper.make_request()
amazon_href_scrapper.output()
google_href_scrapper = HrefScrapper('http://www.google.com', 'google_href.txt')
google_href_scrapper.make_request()
google_href_scrapper.output()
google_image_scrapper = ImageScrapper('http://www.google.com', 'google_image.txt')
google_image_scrapper.make_request()
google_image_scrapper.output()
在上面的代码中,我定义了一个名为Scrapper的基类,它继承自object。这是一个很好的做法,遵循这意味着它将拥有对象拥有的所有方法和值。
此剪贴板概述了存储URL和输出文件的基本配方。然后,它提供了发出请求并将其输出到文件的方法。您会注意到,方法get_elements未实现。这意味着您无法实际实例化此类。
但是,还有一个名为HrefScrapper的类继承自Scrapper,它确实定义了一个get_elements方法。此方法是剪贴板的特定于Href的版本,并且仅从页面获取href属性。
此外,我提供了一个图像刮板,其性能相似,但会刮掉图像源。
在main方法中,您可以看到代码重用的两个示例。第一个是我们为亚马逊创建HrefScraper和为Google创建HrefScraper。创建实例后,我们不需要传递任何其他参数,因为它们存储在实例中。
代码重用的第二个例子是我们如何通过简单地实现get_elements方法来创建ImageScraper或HrefScraper。我们'重用'的代码存在于Scrapper基类中。
答案 2 :(得分:0)
看起来你可以从学习课程中受益。类基本上是可重用代码的蓝图。有很多非常好的资源可以帮助你理解课程。
Python文档 https://docs.python.org/3.4/tutorial/classes.html
Python类教程 http://www.tutorialspoint.com/python/python_classes_objects.htm http://en.wikibooks.org/wiki/A_Beginner%27s_Python_Tutorial/Classes
答案 3 :(得分:0)
Scrapper()只创建该类的实例。要使用类所定义的函数,您需要调用它们。 例如:
s = Scrapper()
s.requests()
有关课程的更多信息,请访问以下链接:http://www.tutorialspoint.com/python/python_classes_objects.htm