2013-05-12 59 views
6

[EDIT 00]: Tôi đã chỉnh sửa nhiều lần bài đăng và bây giờ ngay cả tiêu đề, vui lòng đọc phần bên dưới.Triển khai nội suy chuỗi Python

Tôi chỉ biết về phương pháp chuỗi định dạng, và việc sử dụng nó với từ điển, giống như những người được cung cấp bởi vars(), locals()globals(), ví dụ:

name = 'Ismael' 
print 'My name is {name}.'.format(**vars()) 

Nhưng tôi muốn làm:

name = 'Ismael' 
print 'My name is {name}.' # Similar to ruby 

Vì vậy, tôi đã đưa ra với điều này:

def mprint(string='', dictionary=globals()): 
    print string.format(**dictionary) 

Bạn có thể tương tác với mã ở đây: http://labs.codecademy.com/BA0B/3#:workspace

Cuối cùng, những gì tôi rất thích làm là phải có các chức năng trong một tập tin, tên my_print.py, vì vậy tôi có thể làm:

from my_print import mprint 

name= 'Ismael' 
mprint('Hello! My name is {name}.') 

Nhưng vì nó là ngay bây giờ, có một vấn đề với phạm vi, làm thế nào tôi có thể nhận được không gian tên module chính như một từ điển từ bên trong chức năng in mprint. (không phải là từ số my_print.py)

Tôi hy vọng tôi đã tự mình hiểu, nếu không, hãy thử nhập hàm từ mô-đun khác. (truy nguyên nằm trong liên kết)

Truy cập vào globals() dict từ my_print.py, nhưng tất nhiên tên biến không được xác định trong phạm vi đó, bất kỳ ý tưởng nào về cách thực hiện điều này?

Chức năng hoạt động nếu được xác định trong cùng một mô-đun, nhưng lưu ý cách tôi phải sử dụng globals() vì nếu không tôi sẽ chỉ nhận từ điển có giá trị trong phạm vi mprint().

Tôi đã thử sử dụng ký hiệu không dấu và dấu chấm để truy cập các biến mô-đun chính, nhưng tôi vẫn không thể tìm ra.


[EDIT 01]: Tôi nghĩ rằng tôi đã tìm ra một giải pháp:

Trong my_print.py:

def mprint(string='',dictionary=None): 
    if dictionary is None: 
     import sys 
     caller = sys._getframe(1) 
     dictionary = caller.f_locals 
    print string.format(**dictionary) 

Trong test.py:

from my_print import mprint 

name = 'Ismael' 
country = 'Mexico' 
languages = ['English', 'Spanish'] 

mprint("Hello! My name is {name}, I'm from {country}\n" 
     "and I can speak {languages[1]} and {languages[0]}.") 

Bản in:

Hello! My name is Ismael, I'm from Mexico 
and I can speak Spanish and English. 

Bạn nghĩ sao? Đó là một điều khó khăn đối với tôi!

Tôi thích nó, dễ đọc hơn nhiều đối với tôi.


[EDIT 02]: Tôi đã thực hiện một mô-đun với một chức năng interpolate, một lớp Interpolate và một nỗ lực cho một phương pháp interpolate lớp tương tự như chức năng.

Nó có bộ thử nghiệm nhỏ và được ghi lại!

Tôi bị kẹt với việc triển khai phương pháp, tôi không hiểu.

Đây là mã: http://pastebin.com/N2WubRSB

Bạn nghĩ sao?


[EDIT 03]: Ok tôi đã giải quyết chỉ với interpolate() chức năng cho bây giờ.

Trong string_interpolation.py:

import sys 


def get_scope(scope): 
    scope = scope.lower() 
    caller = sys._getframe(2) 
    options = ['l', 'local', 'g', 'global'] 

    if scope not in options[:2]: 
     if scope in options[2:]: 
      return caller.f_globals 
     else: 
      raise ValueError('invalid mode: {0}'.format(scope)) 
    return caller.f_locals 


def interpolate(format_string=str(),sequence=None,scope='local',returns=False): 
    if type(sequence) is str: 
     scope = sequence 
     sequence = get_scope(scope) 
    else: 
     if not sequence: 
      sequence = get_scope(scope) 

    format = 'format_string.format(**sequence)' 
    if returns is False: 
     print eval(format) 

    elif returns is True: 
     return eval(format) 

Cảm ơn một lần nữa chàng trai! Bạn có ý kiến ​​gì không?


[EDIT 04]:

Đây là phiên bản cuối cùng của tôi, nó có một bài kiểm tra, docstrings và mô tả một số hạn chế tôi đã tìm thấy: http://pastebin.com/ssqbbs57

Bạn có thể nhanh chóng kiểm tra mã ở đây : http://labs.codecademy.com/BBMF#:workspace

Và bản sao Grom git repo ở đây: https://github.com/Ismael-VC/python_string_interpolation.git

+2

liên quan: [? Là một định dạng chuỗi kéo biến từ kêu gọi thực hành xấu phạm vi của nó] (http://stackoverflow.com/questions/13312240/is- a-string-format-that-pull-variables-from-its-calling-scope-bad-practice) – jfs

+1

liên quan: [In tên biến và nội dung dưới dạng công cụ gỡ lỗi; tìm kiếm emacs/Python shortcut] (http://stackoverflow.com/questions/2813227/printing-variable-names-and-contents-as-debugging-tool-looking-for-emacs-python) – jfs

+0

Đây là một bài tập thú vị , nhưng tôi sẽ cảnh báo chống lại kiểu hành vi tiềm ẩn này: Python không khuyến khích nó ("Rõ ràng là tốt hơn là ngầm" nghĩa là ở đây 'mprint ('…', vars())' tốt hơn 'mprint ('…')' quay trở lại người gọi và nhận các biến cục bộ của nó), và tôi nghĩ rằng nó có lý do chính đáng (mã rõ ràng được cho là dễ đọc và duy trì hơn). – EOL

Trả lời

0

Ngôn ngữ thiết kế không chỉ là giải quyết câu đố: ;)

http://www.artima.com/forums/flat.jsp?forum=106&thread=147358

Edit:PEP-0498 giải quyết vấn đề này!

Lớp Template từ mô-đun string, cũng thực hiện những gì tôi cần (nhưng tương tự như phương pháp chuỗi format), cuối cùng nó cũng có khả năng đọc mà tôi tìm kiếm, nó cũng có nhân chứng được đề xuất, nó nằm trong tiêu chuẩn Thư viện và nó cũng có thể dễ dàng tùy chỉnh và mở rộng.

http://docs.python.org/2/library/string.html?highlight=template#string.Template

from string import Template 

name = 'Renata' 
place = 'hospital' 
job = 'Dr.' 
how = 'glad' 
header = '\nTo Ms. {name}:' 

letter = Template(""" 
Hello Ms. $name. 

I'm glad to inform, you've been 
accepted in our $place, and $job Red 
will ${how}ly recieve you tomorrow morning. 
""") 

print header.format(**vars()) 
print letter.substitute(vars()) 

Điều buồn cười là bây giờ tôi nhận được thích hơn của việc sử dụng {} thay vì $ và tôi vẫn như module string_interpolation tôi đã đưa ra, bởi vì nó ít gõ hơn từng mục trong Về lâu dài. LOL!

Run mã ở đây:

http://labs.codecademy.com/BE3n/3#:workspace

1

Một phần vấn đề của bạn - tốt, lý do nó không hoạt động - được đánh dấu trong this question.

Bạn có thể thực hiện chức năng của mình bằng cách chuyển số globals() làm đối số thứ hai, mprint('Hello my name is {name}',globals()).

Mặc dù nó có thể thuận tiện trong Ruby, tôi khuyến khích bạn không viết Ruby bằng Python nếu bạn muốn tận dụng tối đa ngôn ngữ.

+0

Tôi chỉ muốn nhập ít thực sự hơn! ;) Tôi bắt đầu sử dụng thành ngữ ''' .format (** vars())' rất nhiều trong kịch bản của tôi, sau đó tôi reallized tôi đã phải refactor rằng, vì vậy tôi đã (cố gắng), tôi không thực sự quan tâm nếu nó trông giống như ruby ​​hay không, vì tôi không biết gì về lập trình cho đến gần đây, nhưng nó vẫn trông dễ đọc hơn nhiều, và tôi sử dụng nó rất nhiều cho việc định dạng đơn giản. Tôi muốn có thể gọi nó như thế này: 'từ dấu vân tay nhập khẩu của tôi; name = 'Ismael'; mprint ('Xin chào! Tên tôi là {name}.') 'Nếu không có các hình cầu, vv gọi mỗi lần chỉ để biết làm thế nào nó có thể được thực hiện, phải có một cách! – SalchiPapa

+0

Về cơ bản những gì tôi muốn đạt được, là làm cho hành vi mặc định này là: 'mprint ('Xin chào tên tôi là {name}', vars())' mà không gọi một cách rõ ràng vars() mỗi lần.Cảm ơn bạn đã liên kết bằng cách này! – SalchiPapa

2

Mô-đun không chia sẻ không gian tên trong python, vì vậy globals() cho my_print luôn là globals() của tệp my_print.py; tức là vị trí thực sự được xác định.

def mprint(string='', dic = None): 
    dictionary = dic if dic is not None else globals() 
    print string.format(**dictionary) 

Bạn nên chuyển các cụm từ của mô-đun hiện tại() một cách rõ ràng để làm cho nó hoạt động.

An không sử dụng các đối tượng có thể thay đổi làm giá trị mặc định trong các hàm python, nó có thể dẫn đến unexpected results. Sử dụng None làm giá trị mặc định thay thế.

Một ví dụ đơn giản để tìm hiểu phạm vi trong module:

file: my_print.py

x = 10 
def func(): 
    global x 
    x += 1 
    print x 

file: chính.py

from my_print import * 
x = 50 
func() #prints 11 because for func() global scope is still 
     #the global scope of my_print file 
print x #prints 50 
+0

Không có cách nào để lấy không gian tên 'main.py' từ,' my_print.py' như là một dict? Tôi đang đọc về thừa kế, ngay bây giờ, sẽ không phải là một ký hiệu chấm lớp làm các trick? Nhưng sau đó tôi sẽ phải làm cho lớp có thể gọi được ¿? LOL Tôi sẽ gọi nó là một ngày cho bây giờ, cảm ơn Ashwini! – SalchiPapa

+0

Từ tài liệu python: http://docs.python.org/2/library/functions.html#vars Vì vậy, tôi cần nhận main.py '__dict__' từ bên trong dấu vân tay, có thực sự là không thể? Tôi không thể ngừng suy nghĩ về điều này. – SalchiPapa

+0

@ user2374329 Bạn có thể sử dụng 'main .__ dict__', nhưng nó sẽ chỉ chứa các biến được xác định khi' main' được nhập. Thừa kế BTW liên quan đến các lớp không phải là mô-đun. –