פורסם: 16/06/2015 - 10:49
נושא ההודעה: override function within a class in python
|
שלום לכולם
יש לי CALLER בפייתון שמקבל ארועים משרת HTTP
בתוך הCALLER הגדרתי קריאה לפונקציה MAIN של המודול שאני נמצא בו
אבל אם יש לי 2 מודולים שעובדים באותה שיטה אני רוצה שיהיה לי רק CALLER אחד
וכל פעם שהוא יקרא לMAIN המתאים
שמעתי על DECORATORS אבל אני לא יודע אם הם מטפלים בכך .
חשבתי על ירושה של הCALLER ואז כתיבה על פונקציה בתוך הCALLER
עם פרמטר שהוא בעצם השם של הפונקציה שאני רוצה לקרוא לה
ואז אני אכתוב משהוא עם getattr
מישהו יכול לעזור ?
_________________ מערכת: GNU/Linux debian
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 11:40
נושא ההודעה:
|
יש כמה דרכים לעשות את זה, תלוי בדיוק במצב ובאיך הקוד שלך בנוי.
דרך אחת היא לעשות מחלקה אחת (אבסטרקטית, למרות שאין ממש דבר כזה בפייתון נקי), ושני מימושים שלה, שבכל אחד הפונקציה ממומשת כמו שאתה צריך.
דרך אחרת היא להעביר ממש את הפונקציה שאתה הולך לקרוא לה - בפייתון פונקציות הם ערכים לכל דבר, לא צריך להתחיל להתעסק עם שמות וכיוב'.
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 12:06
נושא ההודעה:
|
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 12:19
נושא ההודעה:
|
לא אמרתי שאי אפשר, אמרתי שזה לא ממש חלק מפייתון נקי. עד כמה שאני מבין זה תוספת שבנויה על decorators, לא יכולת של השפה. גם זה שצריך "לרשום" את המחלקות הממשות הופך את זה לפחות אלגנטי.
בכל מקרה, מכיוון שפייתון היא duck-typed אני לא לחלוטין מבין למה צריך את זה, מלבד ולידציה נוספת שכולם "ממשים" את הפונקציות הדרושות.
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 13:23
נושא ההודעה:
|
לא בדיוק, זה משתמש בבסיס ב-meta class, וזה זמין בכל פייתון החל מ־2.6 ומעלה.
בסה"כ זה מספק נוחות, כי מה זה בעצם להגדיר abstract base class ? גם ללא זה, פשוט להגדיר את המחלקה והמתודות, ובכל מתודה שרוצים לחייב שהיורשים יישמו מרימים חריגת NotImplementedError.
בכל מקרה זה overkill למה שצריך פה, אך ללא דוגמאות קוד, קצת קשה לי להבין בדיוק מה רוצים.
נ.ב.
queency, לא צריך להעביר שם של פונקציה ולחפש אותה, אפשר פשוט להעביר את הפונקציה:
קוד: | >>> def say_one():
... print('one')
...
>>> def say_two():
... print('two')
...
>>> def say(fn):
... fn()
...
>>> say(say_one)
one
>>> say(say_two)
two
>>>
|
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 13:42
נושא ההודעה:
|
mksoft : | לא בדיוק, זה משתמש בבסיס ב-meta class, וזה זמין בכל פייתון החל מ־2.6 ומעלה.
בסה"כ זה מספק נוחות, כי מה זה בעצם להגדיר abstract base class ? גם ללא זה, פשוט להגדיר את המחלקה והמתודות, ובכל מתודה שרוצים לחייב שהיורשים יישמו מרימים חריגת NotImplementedError.
|
בדיוק! לכן אני לא מבין למה זה נחוץ. בשפות כמו C++ או Java אתה תופס את הבעיות האלה בזמן קומפילציה (שלא לדבר על זה שאתה חייב את זה מאיך שה-type system בנוי), אבל בפייתון? מה היתרון?
mksoft : |
בכל מקרה זה overkill למה שצריך פה, אך ללא דוגמאות קוד, קצת קשה לי להבין בדיוק מה רוצים.
נ.ב.
queency, לא צריך להעביר שם של פונקציה ולחפש אותה, אפשר פשוט להעביר את הפונקציה:
|
גם זה בדיוק מה שאמרתי בהודעה הראשונה שכתבתי, אבל תמיד טוב לראות דוגמה
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 14:04
נושא ההודעה:
|
קוד: |
#this file called server.py
import BaseHTTPServer
import SimpleHTTPServer
class TestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
# Disable logging DNS lookups
def address_string(self):
return str(self.client_address[0])
def do_GET(s):
"""Respond to a GET request."""
s.send_response(200)
s.send_header("Content-type", "text/html;charset=UTF8")
s.end_headers()
from test_start import fetch_one
tmp = fetch_one()
s.wfile.write(tmp.encode('utf=8')+"\n")
def start_server():
"""Start the server."""
server_address = ("", 70)
server = BaseHTTPServer.HTTPServer(server_address, TestHandler)
server.serve_forever()
#end of server.py
#this file called fetch_one.py
from server import *
def fetch_one():
return "<http><body>*fetch one</body></http>"
if __name__ == "__main__":
print "SERVER UP!"
start_server()
#end of fetch_one.py
|
the fetch_one using the http server
i want to have fetch two as well
but
i want only one script for the http server
could you do that ?
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 14:15
נושא ההודעה:
|
Anonymous : | mksoft : | לא בדיוק, זה משתמש בבסיס ב-meta class, וזה זמין בכל פייתון החל מ־2.6 ומעלה.
בסה"כ זה מספק נוחות, כי מה זה בעצם להגדיר abstract base class ? גם ללא זה, פשוט להגדיר את המחלקה והמתודות, ובכל מתודה שרוצים לחייב שהיורשים יישמו מרימים חריגת NotImplementedError.
|
בדיוק! לכן אני לא מבין למה זה נחוץ. בשפות כמו C++ או Java אתה תופס את הבעיות האלה בזמן קומפילציה (שלא לדבר על זה שאתה חייב את זה מאיך שה-type system בנוי), אבל בפייתון? מה היתרון?
|
הייתרון הוא שהכתיבה היא יותר strict. אתה מחייב את היורשים לממש את הפונקציות (שים לב בדוקומנטציה כתוב שאפשר לממש ולקרוא לפונקציה דרך super)
queency, לפי מה אתה תחליט לאיזה פונצקיה לקרוא? אם זה לפי ה-url, אולי כדאי לעבוד לספרייה שמנהלת urls כמו flask
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 14:36
נושא ההודעה:
|
Anonymous : |
הייתרון הוא שהכתיבה היא יותר strict. |
אבל הולידציה היא רק ברמת runtime, אז זה בדיוק כאילו לא היתה לך הפונקציה במחלקת האב, והיית מקבל AttributeError על פונקציה שלא קיימת.
|
|
חזרה לתוכן הדיון |
פורסם: 16/06/2015 - 14:52
נושא ההודעה:
|
Anonymous : | Anonymous : |
הייתרון הוא שהכתיבה היא יותר strict. |
אבל הולידציה היא רק ברמת runtime, אז זה בדיוק כאילו לא היתה לך הפונקציה במחלקת האב, והיית מקבל AttributeError על פונקציה שלא קיימת. |
זה לא הולידציה. הרעיון הוא שכל מי שהוא לקוח של המחלקה ובנותיה, יודע אילו פונקציות אמורות להיות שם.
מכיוון שאין קומפיילר, גם אין אכיפה של ממש, עד שאתה מנסה ליצור instance (שים לב שהשגיאה היא לא מתי שאתה מנסה לקרוא לפונקציה).
ולמעשה זה יותר interface מאשר abstract class.
|
|
חזרה לתוכן הדיון |
פורסם: 27/06/2015 - 23:31
נושא ההודעה:
|
עדין לא הצליחו לעזור לי לפתור את העניין. (הקפצה)
_________________ מערכת: GNU/Linux debian
|
|
חזרה לתוכן הדיון |
פורסם: 28/06/2015 - 10:12
נושא ההודעה:
|
למה לא לתת את הפונקציה שאתה רוצה שישתמש בה ב-constructor של TestHandler?
קוד: |
class TestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
def __init__(self, f):
self.fetch_func = f
...
def do_GET(s):
"""Respond to a GET request."""
s.send_response(200)
s.send_header("Content-type", "text/html;charset=UTF8")
s.end_headers()
tmp =self.fetch_func()
s.wfile.write(tmp.encode('utf=8')+"\n")
|
|
|
חזרה לתוכן הדיון |
פורסם: 28/06/2015 - 10:16
נושא ההודעה:
|
לחילופין, אם אתה רוצה שאותו אובייקט ידע להשתמש בשתיהן (לא נשמע לי כמו רעיון טוב, אבל מראש אני לא מבין למה זה), אתה יכול לתת את הפונקציה בקריאה ל-do_GET (בהנחה שזו לא פונקציה שאתה דורס, אני לא מכיר את המחלקות הפועלות).
|
|
חזרה לתוכן הדיון |
פורסם: 28/06/2015 - 19:31
נושא ההודעה:
|
קוד: |
#this file called server.py
import BaseHTTPServer
import SimpleHTTPServer
class TestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
# Disable logging DNS lookups
def address_string(self):
return str(self.client_address[0])
def __init__(self,f):
self.my_temp_func = f
def do_GET(s):
"""Respond to a GET request."""
s.send_response(200)
s.send_header("Content-type", "text/html;charset=UTF8")
s.end_headers()
tmp = self.my_temp_func()
s.wfile.write(tmp.encode('utf=8')+"\n")
#end of server.py
#this file called fetch_one.py
import BaseHTTPServer
from server import *
def fetch_one():
return "<http><body>*fetch one</body></http>"
if __name__ == "__main__":
d = TestHandler(fetch_one())
server_address = ("", 70)
server = BaseHTTPServer.HTTPServer(server_address, d)
server.serve_forever()
print "SERVER UP!"
start_server()
#end of fetch_one.py
|
שימוש בצורה כזו נותן לי את הERROR הבא
קוד: |
e]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/SocketServer.py", line 419, in __init__
self.server_bind()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind
SocketServer.TCPServer.server_bind(self)
File "/usr/lib/python2.7/SocketServer.py", line 430, in server_bind
self.socket.bind(self.server_address)
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 13] Permission denied
|
_________________ מערכת: GNU/Linux debian
|
|
חזרה לתוכן הדיון |
פורסם: 28/06/2015 - 21:18
נושא ההודעה:
|
אתה רוצה להעביר את הפונקציה, לא את ערך החזרה שלה. במקום
קוד: |
d = TestHandler(fetch_one())
|
תכתוב
קוד: |
d = TestHandler(fetch_one)
|
|
|
חזרה לתוכן הדיון |
פורסם: 28/06/2015 - 21:22
נושא ההודעה:
|
כמו כן, יש מצב שאתה צריך בקונסטרקטור לקרוא לקונסטרקטור של המחלקה ממנה אתה יורש. יכול להיות שמאותחלים שם דברים, ובגלל שאתה מדלג על זה נוצרות בעיות.
ראה:
http://stackoverflow.com/questions/576169/understanding-python-super-with-init-methods
|
|
חזרה לתוכן הדיון |
פורסם: 29/06/2015 - 00:38
נושא ההודעה:
|
Anonymous : | אתה רוצה להעביר את הפונקציה, לא את ערך החזרה שלה. במקום
קוד: |
d = TestHandler(fetch_one())
|
תכתוב
קוד: |
d = TestHandler(fetch_one)
|
|
גם אחרי התיקון יש את אותה בעיה
_________________ מערכת: GNU/Linux debian
|
|
חזרה לתוכן הדיון |
פורסם: 29/06/2015 - 09:14
נושא ההודעה:
|
queency : | Anonymous : | אתה רוצה להעביר את הפונקציה, לא את ערך החזרה שלה. במקום
קוד: |
d = TestHandler(fetch_one())
|
תכתוב
קוד: |
d = TestHandler(fetch_one)
|
|
גם אחרי התיקון יש את אותה בעיה |
קוד: |
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/SocketServer.py", line 419, in __init__
self.server_bind()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind
SocketServer.TCPServer.server_bind(self)
File "/usr/lib/python2.7/SocketServer.py", line 430, in server_bind
self.socket.bind(self.server_address)
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 13] Permission denied
|
הבעיה היא הרשאות בפתיחת פורט, לא קשורה לאיך הקוד אמור לעבוד...
https://xkcd.com/149/
|
|
חזרה לתוכן הדיון |
פורסם: 30/06/2015 - 09:51
נושא ההודעה:
|
החריגה לא נובעת מהקוד שלי
היא נובעת מהשילוב של הקוד שלי וקוד של BASICHTTPSERVER
כנראה שהפורט נפתח פעמיים
אין לי מספיק ידע לתקן \ לשנות קוד שהוא יחסית אלי NATIVE
יש פיתרון אחר ?
_________________ מערכת: GNU/Linux debian
|
|
חזרה לתוכן הדיון |
פורסם: 30/06/2015 - 10:32
נושא ההודעה:
|
נראה שאתה מנסה להאזין על פורט 80, אם זה המצב, אתה צריך הרשאות root כדי להאזין על פורטים מתחת ל-1024.
|
|
חזרה לתוכן הדיון |
פורסם: 30/06/2015 - 11:45
נושא ההודעה:
|
mksoft : | נראה שאתה מנסה להאזין על פורט 80, אם זה המצב, אתה צריך הרשאות root כדי להאזין על פורטים מתחת ל-1024. |
1) בקוד שלי רואים בבירור שאני עובד בפורט 70
2) ניסיתי על וינדוס גם לא עובד
3)לא עובד עם פתיחת פורט על 7000
_________________ מערכת: GNU/Linux debian
|
|
חזרה לתוכן הדיון |
פורסם: 03/07/2015 - 09:30
נושא ההודעה:
|
מסתבר שכאשר אני בונה פונקציית Init ל TestHandler
אני מקבל
קוד: |
----------------------------------------
Exception happened during processing of request from ('127.0.0.1', 40529)
Traceback (most recent call last):
File "/usr/lib/python2.7/SocketServer.py", line 295, in _handle_request_noblock
self.process_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 321, in process_request
self.finish_request(request, client_address)
File "/usr/lib/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
AttributeError: TestHandler instance has no __call__ method
----------------------------------------
|
יכול להיות שאני דורס איזה INIT אחר למחלקה קדומה יותר
מה הERROR הזה אומר
_________________ מערכת: GNU/Linux debian
|
|
חזרה לתוכן הדיון |
פורסם: 03/07/2015 - 14:40
נושא ההודעה:
|
שאתה מנסה לקרוא למשהו שהוא לא פונקציה.
|
|
חזרה לתוכן הדיון |
פורסם: 03/07/2015 - 14:57
נושא ההודעה:
|
תוספתא: נראה ש-BaseHTTPServer.HTTPServer מצפה לקבל את המחלקה של ה-Handler, ולא Instance של handler. זה אומר שאתה צריך להעביר את שם המחלקה, ולא אינסטנס שלה, וכנראה שה-__init__ חייב להתאים בחתימה.
|
|
חזרה לתוכן הדיון |
פורסם: 07/07/2015 - 10:01
נושא ההודעה:
|
יעצו לי לעשות SUBCLASS ושאר שטויות
הפתרון היה כל כך פשוט שזה כואב
_________________ מערכת: GNU/Linux debian
|
|
חזרה לתוכן הדיון |
|